diff options
224 files changed, 25622 insertions, 5780 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index fb68fdd..cb25ea3 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,6 +1,6 @@ { "git": { - "sha1": "79fcfdf26cf927144ddde1ecf83d0716441c5e45" + "sha1": "4dbe66da6a922c64436a8f3a00a4ab1f0ebafbb6" }, - "path_in_vcs": "" + "path_in_vcs": "pdl-compiler" }
\ No newline at end of file @@ -3,39 +3,11 @@ // because the changes will be overridden on upgrade. // Content before the first "rust_*" or "genrule" module is preserved. -rust_binary_host { - name: "generate_canonical_tests", - crate_name: "generate_canonical_tests", - cargo_env_compat: true, - cargo_pkg_version: "0.2.3", - crate_root: "src/bin/generate-canonical-tests.rs", - edition: "2021", - features: [ - "default", - "serde", - ], - rustlibs: [ - "libargh", - "libcodespan_reporting", - "libheck", - "libpdl_compiler", - "libpest", - "libprettyplease", - "libproc_macro2", - "libquote", - "libserde", - "libserde_json", - "libsyn", - ], - proc_macros: ["libpest_derive"], - compile_multilib: "first", -} - rust_library_host { name: "libpdl_compiler", crate_name: "pdl_compiler", cargo_env_compat: true, - cargo_pkg_version: "0.2.3", + cargo_pkg_version: "0.3.0", crate_root: "src/lib.rs", edition: "2021", features: [ @@ -62,7 +34,7 @@ rust_binary_host { name: "pdlc", crate_name: "pdlc", cargo_env_compat: true, - cargo_pkg_version: "0.2.3", + cargo_pkg_version: "0.3.0", crate_root: "src/main.rs", edition: "2021", features: [ @@ -100,6 +72,20 @@ genrule_defaults { ], } +// Defaults for legacy rust backend generation. +genrule_defaults { + name: "pdl_rust_legacy_generator_defaults", + cmd: "$(location :pdlc) --output-format rust_legacy $(in) > $(out)", + tools: [":pdlc"], + defaults_visibility: [ + "//system/nfc:__subpackages__", + "//external/rust/pica", + "//external/uwb/src", + "//packages/modules/Bluetooth:__subpackages__", + "//tools/netsim:__subpackages__", + ], +} + // Defaults for rust_noalloc backend generation. genrule_defaults { name: "pdl_rust_noalloc_generator_defaults", @@ -128,79 +114,7 @@ genrule_defaults { filegroup { name: "pdl_generated_files", srcs: [ - "tests/generated/custom_field_declaration_big_endian.rs", - "tests/generated/custom_field_declaration_little_endian.rs", - "tests/generated/enum_declaration_big_endian.rs", - "tests/generated/enum_declaration_little_endian.rs", - "tests/generated/packet_decl_8bit_enum_array_big_endian.rs", - "tests/generated/packet_decl_8bit_enum_array_little_endian.rs", - "tests/generated/packet_decl_8bit_enum_big_endian.rs", - "tests/generated/packet_decl_8bit_enum_little_endian.rs", - "tests/generated/packet_decl_8bit_scalar_array_big_endian.rs", - "tests/generated/packet_decl_8bit_scalar_array_little_endian.rs", - "tests/generated/packet_decl_8bit_scalar_big_endian.rs", - "tests/generated/packet_decl_8bit_scalar_little_endian.rs", - "tests/generated/packet_decl_24bit_enum_array_big_endian.rs", - "tests/generated/packet_decl_24bit_enum_array_little_endian.rs", - "tests/generated/packet_decl_24bit_enum_big_endian.rs", - "tests/generated/packet_decl_24bit_enum_little_endian.rs", - "tests/generated/packet_decl_24bit_scalar_array_big_endian.rs", - "tests/generated/packet_decl_24bit_scalar_array_little_endian.rs", - "tests/generated/packet_decl_24bit_scalar_big_endian.rs", - "tests/generated/packet_decl_24bit_scalar_little_endian.rs", - "tests/generated/packet_decl_64bit_enum_array_big_endian.rs", - "tests/generated/packet_decl_64bit_enum_array_little_endian.rs", - "tests/generated/packet_decl_64bit_enum_big_endian.rs", - "tests/generated/packet_decl_64bit_enum_little_endian.rs", - "tests/generated/packet_decl_64bit_scalar_array_big_endian.rs", - "tests/generated/packet_decl_64bit_scalar_array_little_endian.rs", - "tests/generated/packet_decl_64bit_scalar_big_endian.rs", - "tests/generated/packet_decl_64bit_scalar_little_endian.rs", - "tests/generated/packet_decl_array_dynamic_count_big_endian.rs", - "tests/generated/packet_decl_array_dynamic_count_little_endian.rs", - "tests/generated/packet_decl_array_dynamic_size_big_endian.rs", - "tests/generated/packet_decl_array_dynamic_size_little_endian.rs", - "tests/generated/packet_decl_array_unknown_element_width_dynamic_count_big_endian.rs", - "tests/generated/packet_decl_array_unknown_element_width_dynamic_count_little_endian.rs", - "tests/generated/packet_decl_array_unknown_element_width_dynamic_size_big_endian.rs", - "tests/generated/packet_decl_array_unknown_element_width_dynamic_size_little_endian.rs", - "tests/generated/packet_decl_array_with_padding_big_endian.rs", - "tests/generated/packet_decl_array_with_padding_little_endian.rs", - "tests/generated/packet_decl_child_packets_big_endian.rs", - "tests/generated/packet_decl_child_packets_little_endian.rs", - "tests/generated/packet_decl_complex_scalars_big_endian.rs", - "tests/generated/packet_decl_complex_scalars_little_endian.rs", - "tests/generated/packet_decl_custom_field_big_endian.rs", - "tests/generated/packet_decl_custom_field_little_endian.rs", - "tests/generated/packet_decl_empty_big_endian.rs", - "tests/generated/packet_decl_empty_little_endian.rs", - "tests/generated/packet_decl_fixed_enum_field_big_endian.rs", - "tests/generated/packet_decl_fixed_enum_field_little_endian.rs", - "tests/generated/packet_decl_fixed_scalar_field_big_endian.rs", - "tests/generated/packet_decl_fixed_scalar_field_little_endian.rs", - "tests/generated/packet_decl_grand_children_big_endian.rs", - "tests/generated/packet_decl_grand_children_little_endian.rs", - "tests/generated/packet_decl_mask_scalar_value_big_endian.rs", - "tests/generated/packet_decl_mask_scalar_value_little_endian.rs", - "tests/generated/packet_decl_mixed_scalars_enums_big_endian.rs", - "tests/generated/packet_decl_mixed_scalars_enums_little_endian.rs", - "tests/generated/packet_decl_parent_with_alias_child_big_endian.rs", - "tests/generated/packet_decl_parent_with_alias_child_little_endian.rs", - "tests/generated/packet_decl_parent_with_no_payload_big_endian.rs", - "tests/generated/packet_decl_parent_with_no_payload_little_endian.rs", - "tests/generated/packet_decl_payload_field_unknown_size_big_endian.rs", - "tests/generated/packet_decl_payload_field_unknown_size_little_endian.rs", - "tests/generated/packet_decl_payload_field_unknown_size_terminal_big_endian.rs", - "tests/generated/packet_decl_payload_field_unknown_size_terminal_little_endian.rs", - "tests/generated/packet_decl_payload_field_variable_size_big_endian.rs", - "tests/generated/packet_decl_payload_field_variable_size_little_endian.rs", - "tests/generated/packet_decl_reserved_field_big_endian.rs", - "tests/generated/packet_decl_reserved_field_little_endian.rs", - "tests/generated/packet_decl_simple_scalars_big_endian.rs", - "tests/generated/packet_decl_simple_scalars_little_endian.rs", - "tests/generated/preamble.rs", - "tests/generated/struct_decl_complex_scalars_big_endian.rs", - "tests/generated/struct_decl_complex_scalars_little_endian.rs", + "tests/generated/rust/**/*.rs", ], } @@ -242,10 +156,16 @@ genrule { rust_test_host { name: "pdl_generated_files_compile", srcs: [":pdl_generated_files_compile_rs"], + features: ["serde"], + rustlibs: [ + "libbytes", + "libserde", + "libtempfile", + "libpdl_runtime", + ], test_suites: ["general-tests"], clippy_lints: "none", lints: "none", - defaults: ["pdl_backend_defaults"], } // The generators support more features for LE packets than for BE @@ -274,10 +194,8 @@ genrule { out: ["be_test_file.pdl"], } -// Generate the Rust parser+serializer backends. genrule { - name: "pdl_le_backend", - tools: [":pdlc"], + name: "pdl_rust_generator_tests_le_src", cmd: "$(location :pdlc)" + " --output-format rust" + " --exclude-declaration UnsizedCustomField" + @@ -300,14 +218,18 @@ genrule { " --exclude-declaration Packet_Array_Field_UnsizedElement_SizeModifier" + " --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier_" + " --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier" + - " $(in) > $(out)", - srcs: ["tests/canonical/le_test_file.pdl"], - out: ["le_backend.rs"], + " $(location tests/canonical/le_test_file.pdl) > $(out);" + + "$(location :pdlc) $(location tests/canonical/le_test_vectors.json) --output-format rust --tests >> $(out)", + srcs: [ + "tests/canonical/le_test_file.pdl", + "tests/canonical/le_test_vectors.json", + ], + out: ["le_canonical.rs"], + tools: [":pdlc"], } genrule { - name: "pdl_be_backend", - tools: [":pdlc"], + name: "pdl_rust_generator_tests_be_src", cmd: "$(location :pdlc)" + " --output-format rust" + " --exclude-declaration UnsizedCustomField" + @@ -324,64 +246,26 @@ genrule { " --exclude-declaration Packet_Array_Field_UnsizedElement_SizeModifier" + " --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier_" + " --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier" + - " $(in) > $(out)", - srcs: [":pdl_be_test_file"], - out: ["be_backend.rs"], -} - -rust_defaults { - name: "pdl_backend_defaults", - features: ["serde"], - rustlibs: [ - "libbytes", - "libserde", - "libtempfile", - "libpdl_runtime", + " $(location :pdl_be_test_file) > $(out);" + + "$(location :pdlc) $(location tests/canonical/be_test_vectors.json) --output-format rust --tests >> $(out)", + srcs: [ + ":pdl_be_test_file", + "tests/canonical/be_test_vectors.json", ], -} - -rust_library_host { - name: "libpdl_le_backend", - crate_name: "pdl_le_backend", - srcs: [":pdl_le_backend"], - defaults: ["pdl_backend_defaults"], - clippy_lints: "none", - lints: "none", -} - -rust_library_host { - name: "libpdl_be_backend", - crate_name: "pdl_be_backend", - srcs: [":pdl_be_backend"], - defaults: ["pdl_backend_defaults"], - clippy_lints: "none", - lints: "none", -} - -genrule { - name: "pdl_rust_generator_tests_le_src", - cmd: "$(location :generate_canonical_tests) $(in) pdl_le_backend > $(out)", - srcs: ["tests/canonical/le_test_vectors.json"], - out: ["le_canonical.rs"], - tools: [":generate_canonical_tests"], -} - -genrule { - name: "pdl_rust_generator_tests_be_src", - cmd: "$(location :generate_canonical_tests) $(in) pdl_be_backend > $(out)", - srcs: ["tests/canonical/be_test_vectors.json"], out: ["be_canonical.rs"], - tools: [":generate_canonical_tests"], + tools: [":pdlc"], } rust_test_host { name: "pdl_rust_generator_tests_le", srcs: [":pdl_rust_generator_tests_le_src"], test_suites: ["general-tests"], + features: ["serde"], rustlibs: [ + "libbytes", "libnum_traits", - "libpdl_le_backend", "libpdl_runtime", + "libserde", "libserde_json", ], clippy_lints: "none", @@ -392,10 +276,12 @@ rust_test_host { name: "pdl_rust_generator_tests_be", srcs: [":pdl_rust_generator_tests_be_src"], test_suites: ["general-tests"], + features: ["serde"], rustlibs: [ + "libbytes", "libnum_traits", - "libpdl_be_backend", "libpdl_runtime", + "libserde", "libserde_json", ], clippy_lints: "none", @@ -410,6 +296,10 @@ genrule { cmd: "set -o pipefail;" + " $(location :pdlc) $(in) |" + " $(location :pdl_python_generator)" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_ConstantSize" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_VariableSize" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_VariableCount" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_UnknownSize" + " --output $(out) --custom-type-location tests.custom_types", tool_files: [ "tests/custom_types.py", @@ -430,6 +320,10 @@ genrule { cmd: "set -o pipefail;" + " $(location :pdlc) $(in) |" + " $(location :pdl_python_generator)" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_ConstantSize" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_VariableSize" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_VariableCount" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_UnknownSize" + " --output $(out) --custom-type-location tests.custom_types", tool_files: [ "tests/custom_types.py", @@ -486,6 +380,28 @@ genrule { cmd: "set -o pipefail;" + " $(location :pdlc) $(in) |" + " $(location :pdl_cxx_generator)" + + " --exclude-declaration Packet_Custom_Field_ConstantSize" + + " --exclude-declaration Packet_Custom_Field_VariableSize" + + " --exclude-declaration Packet_Checksum_Field_FromStart" + + " --exclude-declaration Packet_Checksum_Field_FromEnd" + + " --exclude-declaration Struct_Custom_Field_ConstantSize" + + " --exclude-declaration Struct_Custom_Field_VariableSize" + + " --exclude-declaration Struct_Checksum_Field_FromStart" + + " --exclude-declaration Struct_Checksum_Field_FromEnd" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_ConstantSize" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_VariableSize" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_VariableCount" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_UnknownSize" + + " --exclude-declaration Struct_Custom_Field_ConstantSize_" + + " --exclude-declaration Struct_Custom_Field_VariableSize_" + + " --exclude-declaration Struct_Checksum_Field_FromStart_" + + " --exclude-declaration Struct_Checksum_Field_FromEnd_" + + " --exclude-declaration PartialParent5" + + " --exclude-declaration PartialChild5_A" + + " --exclude-declaration PartialChild5_B" + + " --exclude-declaration PartialParent12" + + " --exclude-declaration PartialChild12_A" + + " --exclude-declaration PartialChild12_B" + " --namespace le_test" + " --output $(out)", srcs: [ @@ -535,6 +451,28 @@ genrule { cmd: "set -o pipefail;" + " $(location :pdlc) $(in) |" + " $(location :pdl_cxx_generator)" + + " --exclude-declaration Packet_Custom_Field_ConstantSize" + + " --exclude-declaration Packet_Custom_Field_VariableSize" + + " --exclude-declaration Packet_Checksum_Field_FromStart" + + " --exclude-declaration Packet_Checksum_Field_FromEnd" + + " --exclude-declaration Struct_Custom_Field_ConstantSize" + + " --exclude-declaration Struct_Custom_Field_VariableSize" + + " --exclude-declaration Struct_Checksum_Field_FromStart" + + " --exclude-declaration Struct_Checksum_Field_FromEnd" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_ConstantSize" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_VariableSize" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_VariableCount" + + " --exclude-declaration Packet_Array_Field_VariableElementSize_UnknownSize" + + " --exclude-declaration Struct_Custom_Field_ConstantSize_" + + " --exclude-declaration Struct_Custom_Field_VariableSize_" + + " --exclude-declaration Struct_Checksum_Field_FromStart_" + + " --exclude-declaration Struct_Checksum_Field_FromEnd_" + + " --exclude-declaration PartialParent5" + + " --exclude-declaration PartialChild5_A" + + " --exclude-declaration PartialChild5_B" + + " --exclude-declaration PartialParent12" + + " --exclude-declaration PartialChild12_A" + + " --exclude-declaration PartialChild12_B" + " --namespace be_test" + " --output $(out)", srcs: [ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index b16bd94..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,33 +0,0 @@ -# How to contribute - -We'd love to accept your patches and contributions to this project. - -## Before you begin - -### Sign our Contributor License Agreement - -Contributions to this project must be accompanied by a -[Contributor License Agreement](https://cla.developers.google.com/about) (CLA). -You (or your employer) retain the copyright to your contribution; this simply -gives us permission to use and redistribute your contributions as part of the -project. - -If you or your current employer have already signed the Google CLA (even if it -was for a different project), you probably don't need to do it again. - -Visit <https://cla.developers.google.com/> to see your current agreements or to -sign a new one. - -### Review our community guidelines - -This project follows -[Google's Open Source Community Guidelines](https://opensource.google/conduct/). - -## Contribution process - -### Code reviews - -All submissions, including submissions by project members, require review. We -use GitHub pull requests for this purpose. Consult -[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more -information on using pull requests. @@ -12,7 +12,7 @@ [package] edition = "2021" name = "pdl-compiler" -version = "0.2.3" +version = "0.3.0" authors = [ "Henri Chataing <henrichataing@google.com>", "David de Jesus Duarte <licorne@google.com>", diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 4d86b22..bfd1edf 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "pdl-compiler" -version = "0.2.3" +version = "0.3.0" edition = "2021" description = "Parser and serializer generator for protocol binary packets" repository = "https://github.com/google/pdl/" @@ -1,23 +1,20 @@ # This project was upgraded with external_updater. -# Usage: tools/external_updater/updater.sh update rust/crates/pdl-compiler +# Usage: tools/external_updater/updater.sh update external/rust/crates/pdl-compiler # For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md name: "pdl-compiler" description: "Parser and serializer generator for protocol binary packets" third_party { - url { - type: HOMEPAGE - value: "https://crates.io/crates/pdl-compiler" - } - url { - type: ARCHIVE - value: "https://static.crates.io/crates/pdl-compiler/pdl-compiler-0.2.3.crate" - } - version: "0.2.3" license_type: NOTICE last_upgrade_date { - year: 2023 - month: 11 - day: 13 + year: 2024 + month: 5 + day: 29 + } + homepage: "https://crates.io/crates/pdl-compiler" + identifier { + type: "Archive" + value: "https://static.crates.io/crates/pdl-compiler/pdl-compiler-0.3.0.crate" + version: "0.3.0" } } @@ -45,5 +45,5 @@ Language specific instructions are provided for all supported backends: ## Similar projects - [Kaitai](https://kaitai.io) -- [EMBOSS](https://github.com/kimrutherford/EMBOSS) +- [Emboss](https://github.com/google/emboss) - [P4](https://p4.org/p4-spec/docs/P4-16-v1.0.0-spec.html) diff --git a/doc/cxx-generated-code-guide.rst b/doc/cxx-generated-code-guide.rst deleted file mode 100644 index 3a71430..0000000 --- a/doc/cxx-generated-code-guide.rst +++ /dev/null @@ -1,47 +0,0 @@ -C++ Generated Code Guide -======================== - -Usage ------ - -.. sourcecode:: bash - - usage: generate_cxx_backend.py [-h] [--input INPUT] [--output OUTPUT] [--namespace NAMESPACE] [--include-header INCLUDE_HEADER] [--using-namespace USING_NAMESPACE] - - options: - -h, --help show this help message and exit - --input INPUT Input PDL-JSON source - --output OUTPUT Output C++ file - --namespace NAMESPACE - Generated module namespace - --include-header INCLUDE_HEADER - Added include directives - --using-namespace USING_NAMESPACE - Added using namespace statements - -Example invocation: - -.. sourcecode:: bash - - 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 deleted file mode 100644 index de766d4..0000000 --- a/doc/python-generated-code-guide.rst +++ /dev/null @@ -1,126 +0,0 @@ -Python Generated Code Guide -=========================== - -Usage ------ - -.. sourcecode:: bash - - usage: generate_python_backend.py [-h] [--input INPUT] [--output OUTPUT] [--custom-type-location CUSTOM_TYPE_LOCATION] - - options: - -h, --help show this help message and exit - --input INPUT Input PDL-JSON source - --output OUTPUT Output Python file - --custom-type-location CUSTOM_TYPE_LOCATION - Module of declaration of custom types - -Example invocation: - -.. sourcecode:: bash - - cargo run my-protocol.pdl --output-format json | \ - ./scripts/generate_python_backend.py > my-protocol.py - -Language bindings ------------------ - -The generator produces a pure python implementation of the parser and serializer -for the selected grammar, using only builtin features of the Python language. -The generated constructs are all type annotated and _should_ pass the type -validation. - -All packets inherit either from their parent declaration or at the root -a blanket `Packet` class implementation. - -.. sourcecode:: python - - @dataclass - class Packet: - payload: Optional[bytes] = field(repr=False, default_factory=bytes, compare=False) - -Enum declarations -^^^^^^^^^^^^^^^^^ - -+---------------------------------------+---------------------------------------------------------------+ -| :: | .. sourcecode:: python | -| | | -| enum TestEnum : 8 { | class TestEnum(enum.IntEnum): | -| A = 1, | A = 1 | -| B = 2..3, | B_MIN = 2 | -| C = 4, | B_MAX = 3 | -| OTHER = .., | C = 4 | -| } | | -+---------------------------------------+---------------------------------------------------------------+ - -.. note:: - Python enums are open by construction, default cases in enum declarations are ignored. - -Packet declarations -^^^^^^^^^^^^^^^^^^^ - -+---------------------------------------+---------------------------------------------------------------+ -| :: | .. sourcecode:: python | -| | | -| packet TestPacket { | @dataclass | -| a: 8, | packet TestPacket(Packet): | -| b: TestEnum, | a: int = field(kw_only=True, default=0) | -| } | b: TestEnum = field(kw_only=True, default=TestEnum.A) | -| | | -| | @staticmethod | -| | def parse(span: bytes) -> Tuple['TestPacket', bytes]: | -| | pass | -| | | -| | def serialize(self, payload: bytes = None) -> bytes: | -| | pass | -| | | -| | @property | -| | def size(self) -> int: | -| | pass | -+---------------------------------------+---------------------------------------------------------------+ -| :: | .. sourcecode:: python | -| | | -| packet TestPacket: ParentPacket { | @dataclass | -| a: 8, | packet TestPacket(ParentPacket): | -| b: TestEnum, | a: int = field(kw_only=True, default=0) | -| } | b: TestEnum = field(kw_only=True, default=TestEnum.A) | -| | | -| | @staticmethod | -| | def parse(span: bytes) -> Tuple['TestPacket', bytes]: | -| | pass | -| | | -| | def serialize(self, payload: bytes = None) -> bytes: | -| | pass | -| | | -| | @property | -| | def size(self) -> int: | -| | pass | -+---------------------------------------+---------------------------------------------------------------+ - -Field declarations -^^^^^^^^^^^^^^^^^^ - -Fields without a binding name do not have a concrete representation in the -generated class, but are nonetheless validated during parsing or implicitely -generated during serialization. - -+---------------------------------------+---------------------------------------------------------------+ -| :: | .. sourcecode:: python | -| | | -| a: 8 | a: int = field(kw_only=True, default=0) | -+---------------------------------------+---------------------------------------------------------------+ -| :: | .. sourcecode:: python | -| | | -| a: TestEnum, | a: TestEnum = field(kw_only=True, default=TestEnum.A) | -| b: TestStruct | b: TestStruct = field(kw_only=True, | -| | default_factory=TestStruct) | -+---------------------------------------+---------------------------------------------------------------+ -| :: | .. sourcecode:: python | -| | | -| a: 8[], | a: List[int] = field(kw_only=True, default_factory=list) | -| b: 16[128], | b: List[int] = field(kw_only=True, default_factory=list) | -| c: TestEnum[], | c: List[TestEnum] = field(kw_only=True, | -| d: TestStruct[] | default_factory=list) | -| | d: List[TestStruct] = field(kw_only=True, | -| | default_factory=list) | -+---------------------------------------+---------------------------------------------------------------+ diff --git a/doc/reference.md b/doc/reference.md deleted file mode 100644 index ce2f0a7..0000000 --- a/doc/reference.md +++ /dev/null @@ -1,692 +0,0 @@ -# Packet Description Language - -[TOC] - -## Notation - -| Notation | Example | Meaning | -|:-------------:|:----------------------------:|:----------------------------------------------------:| -| __ANY__ | __ANY__ | Any character | -| CAPITAL | IDENTIFIER, INT | A token production | -| snake_case | declaration, constraint | A syntactical production | -| `string` | `enum`, `=` | The exact character(s) | -| \x | \n, \r, \t, \0 | The character represented by this escape | -| x? | `,`? | An optional item | -| x* | ALPHANUM* | 0 or more of x | -| x+ | HEXDIGIT+ | 1 or more of x | -| x \| y | ALPHA \| DIGIT, `0x` \| `0X` | Either x or y | -| [x-y] | [`a`-`z`] | Any of the characters in the range from x to y | -| !x | !\n | Negative Predicate (lookahead), do not consume input | -| () | (`,` enum_tag) | Groups items | - - -[WHITESPACE](#Whitespace) and [COMMENT](#Comment) are implicitly inserted between every item -and repetitions in syntactical rules (snake_case). - -``` -file: endianess declaration* -``` -behaves like: -``` -file: (WHITESPACE | COMMENT)* endianess (WHITESPACE | COMMENT)* (declaration | WHITESPACE | COMMENT)* -``` - -## File - -> file:\ -> endianess [declaration](#declarations)* -> -> endianess:\ -> `little_endian_packets` | `big_endian_packets` - -The structure of a `.pdl`file is: -1. A declaration of the protocol endianess: `little_endian_packets` or `big_endian_packets`. Followed by -2. Declarations describing the structure of the protocol. - -``` -// The protocol is little endian -little_endian_packets - -// Brew a coffee -packet Brew { - pot: 8, // Output Pot: 8bit, 0-255 - additions: CoffeeAddition[2] // Coffee Additions: array of 2 CoffeeAddition -} -``` - -The endianess affects how fields of fractional byte sizes (hence named -bit-fields) are parsed or serialized. Such fields are grouped together to the -next byte boundary, least significant bit first, and then byte-swapped to the -required endianess before being written to memory, or after being read from -memory. - -``` -packet Coffee { - a: 1, - b: 15, - c: 3, - d: 5, -} - -// The first two field are laid out as a single -// integer of 16-bits -// MSB LSB -// 16 8 0 -// +---------------------------------------+ -// | b14 .. .. b0 |a| -// +---------------------------------------+ -// -// The file endianness is applied to this integer -// to obtain the byte layout of the packet fields. -// -// Little endian layout -// MSB LSB -// 7 6 5 4 3 2 1 0 -// +---------------------------------------+ -// 0 | b[6:0] | a | -// +---------------------------------------+ -// 1 | b[14:7] | -// +---------------------------------------+ -// 2 | d | c | -// +---------------------------------------+ -// -// Big endian layout -// MSB LSB -// 7 6 5 4 3 2 1 0 -// +---------------------------------------+ -// 0 | b[14:7] | -// +---------------------------------------+ -// 1 | b[6:0] | a | -// +---------------------------------------+ -// 2 | d | c | -// +---------------------------------------+ -``` - -Fields which qualify as bit-fields are: -- [Scalar](#fields-scalar) fields -- [Size](#fields-size) fields -- [Count](#fields-count) fields -- [Fixed](#fields-fixed) fields -- [Reserved](#fields-reserved) fields -- [Typedef](#fields-typedef) fields, when the field type is an - [Enum](#enum) - -Fields that do not qualify as bit-fields _must_ start and end on a byte boundary. - -## Identifiers - -- Identifiers can denote a field; an enumeration tag; or a declared type. - -- Field identifiers declared in a [packet](#packet) (resp. [struct](#struct)) belong to the _scope_ that extends - to the packet (resp. struct), and all derived packets (resp. structs). - -- Field identifiers declared in a [group](#group) belong to the _scope_ that - extends to the packets declaring a [group field](#group_field) for this group. - -- Two fields may not be declared with the same identifier in any packet scope. - -- Two types may not be declared width the same identifier. - -## Declarations - -> declaration: {#declaration}\ -> [enum_declaration](#enum) |\ -> [packet_declaration](#packet) |\ -> [struct_declaration](#struct) |\ -> [group_declaration](#group) |\ -> [checksum_declaration](#checksum) |\ -> [custom_field_declaration](#custom-field) |\ -> [test_declaration](#test) - -A *declaration* defines a type inside a `.pdl` file. A declaration can reference -another declaration appearing later in the file. - -A declaration is either: -- an [Enum](#enum) declaration -- a [Packet](#packet) declaration -- a [Struct](#struct) declaration -- a [Group](#group) declaration -- a [Checksum](#checksum) declaration -- a [Custom Field](#custom-field) declaration -- a [Test](#test) declaration - -### Enum - -> enum_declaration:\ -> `enum` [IDENTIFIER](#identifier) `:` [INTEGER](#integer) `{`\ -> enum_tag_list\ -> `}` -> -> enum_tag_list:\ -> enum_tag (`,` enum_tag)* `,`? -> -> enum_tag:\ -> enum_range | enum_value | enum_other -> -> enum_range:\ -> [IDENTIFIER](#identifier) `=` [INTEGER](#integer) `..` [INTEGER](#integer)) (`{`\ -> enum_value_list\ -> `}`)? -> -> enum_value_list:\ -> enum_value (`,` enum_value)* `,`? -> -> enum_value:\ -> [IDENTIFIER](#identifier) `=` [INTEGER](#integer) -> -> enum_other:\ -> [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. - -``` -enum CoffeeAddition: 5 { - Empty = 0, - - NonAlcoholic = 1..9 { - Cream = 1, - Vanilla = 2, - Chocolate = 3, - }, - - Alcoholic = 10..19 { - Whisky = 10, - Rum = 11, - Kahlua = 12, - Aquavit = 13, - }, - - Custom = 20..29, - - Other = .. -} -``` - -### Packet - -> packet_declaration:\ -> `packet` [IDENTIFIER](#identifier)\ -> (`:` [IDENTIFIER](#identifier)\ -> (`(` [constraint_list](#constraints) `)`)?\ -> )?\ -> `{`\ -> [field_list](#fields)?\ -> `}` - -A *packet* is a declaration of a sequence of [fields](#fields). While packets -can contain bit-fields, the size of the whole packet must be a multiple of 8 -bits. - -A *packet* can optionally inherit from another *packet* declaration. In this case the packet -inherits the parent's fields and the child's fields replace the -[*\_payload\_*](#fields-payload) or [*\_body\_*](#fields-body) field of the parent. - -When inheriting, you can use constraints to set values on parent fields. -See [constraints](#constraints) for more details. - -``` -packet Error { - code: 32, - _payload_ -} - -packet ImATeapot: Error(code = 418) { - brand_id: 8 -} -``` - -### Struct - -> struct_declaration:\ -> `struct` [IDENTIFIER](#identifier)\ -> (`:` [IDENTIFIER](#identifier)\ -> (`(` [constraint_list](#constraints) `)`)?\ -> )?\ -> `{`\ -> [field_list](#fields)?\ -> `}` - -A *struct* follows the same rules as a [*packet*](#packet) with the following differences: -- It inherits from a *struct* declaration instead of *packet* declaration. -- A [typedef](#fields-typedef) field can reference a *struct*. - -### Group - -> group_declaration:\ -> `group` [IDENTIFIER](#identifier) `{`\ -> [field_list](#fields)\ -> `}` - -A *group* is a sequence of [fields](#fields) that expand in a -[packet](#packet) or [struct](#struct) when used. - -See also the [Group field](#fields-group). - -``` -group Paged { - offset: 8, - limit: 8 -} - -packet AskBrewHistory { - pot: 8, // Coffee Pot - Paged -} -``` -behaves like: -``` -packet AskBrewHistory { - pot: 8, // Coffee Pot - offset: 8, - limit: 8 -} -``` - -### Checksum - -> checksum_declaration:\ -> `checksum` [IDENTIFIER](#identifier) `:` [INTEGER](#integer) [STRING](#string) - -A *checksum* is a native type (not implemented in PDL). See your generator documentation -for more information on how to use it. - -The [integer](#integer) following the name specify the bit size of the checksum value. -The [string](#string) following the size is a value defined by the generator implementation. - -``` -checksum CRC16: 16 "crc16" -``` - -### Custom Field - -> custom_field_declaration:\ -> `custom_field` [IDENTIFIER](#identifier) (`:` [INTEGER](#integer))? [STRING](#string) - -A *custom field* is a native type (not implemented in PDL). See your generator documentation for more -information on how to use it. - -If present, the [integer](#integer) following the name specify the bit size of the value. -The [string](#string) following the size is a value defined by the generator implementation. - -``` -custom_field URL "url" -``` - -### Test - -> test_declaration:\ -> `test` [IDENTIFIER](#identifier) `{`\ -> test_case_list\ -> `}` -> -> test_case_list:\ -> test_case (`,` test_case)* `,`? -> -> test_case:\ -> [STRING](#string) - -A *test* declares a set of valid octet representations of a packet identified by its name. -The generator implementation defines how to use the test data. - -A test passes if the packet parser accepts the input; if you want to test -the values returned for each field, you may specify a derived packet with field values enforced using -constraints. - -``` -packet Brew { - pot: 8, - addition: CoffeeAddition -} - -test Brew { - "\x00\x00", - "\x00\x04" -} - -// Fully Constrained Packet -packet IrishCoffeeBrew: Brew(pot = 0, additions_list = Whisky) {} - -test IrishCoffeeBrew { - "\x00\x04" -} -``` - -## Constraints - -> constraint:\ -> [IDENTIFIER](#identifier) `=` [IDENTIFIER](#identifier) | [INTEGER](#integer) -> -> constraint_list:\ -> constraint (`,` constraint)* `,`? - -A *constraint* defines the value of a parent field. -The value can either be an [enum](#enum) tag or an [integer](#integer). - -``` -group Additionable { - addition: CoffeAddition -} - -packet IrishCoffeeBrew { - pot: 8, - Additionable { - addition = Whisky - } -} - -packet Pot0IrishCoffeeBrew: IrishCoffeeBrew(pot = 0) {} -``` - -## Fields - -> field_list:\ -> field (`,` field)* `,`? -> -> field:\ -> [checksum_field](#fields-checksum) |\ -> [padding_field](#fields-padding) |\ -> [size_field](#fields-size) |\ -> [count_field](#fields-count) |\ -> [payload_field](#fields-payload) |\ -> [body_field](#fields-body) |\ -> [fixed_field](#fields-fixed) |\ -> [reserved_field](#fields-reserved) |\ -> [array_field](#fields-array) |\ -> [scalar_field](#fields-scalar) |\ -> [typedef_field](#fields-typedef) |\ -> [group_field](#fields-group) - -A field is either: -- a [Scalar](#fields-scalar) field -- a [Typedef](#fields-typedef) field -- a [Group](#fields-group) field -- an [Array](#fields-array) field -- a [Size](#fields-size) field -- a [Count](#fields-count) field -- a [Payload](#fields-payload) field -- a [Body](#fields-body) field -- a [Fixed](#fields-fixed) field -- a [Checksum](#fields-checksum) field -- a [Padding](#fields-padding) field -- a [Reserved](#fields-reserved) field - -### Scalar {#fields-scalar} - -> scalar_field:\ -> [IDENTIFIER](#identifier) `:` [INTEGER](#integer) - -A *scalar* field defines a numeric value with a bit size. - -``` -struct Coffee { - temperature: 8 -} -``` - -### Typedef {#fields-typedef} - -> typedef_field:\ -> [IDENTIFIER](#identifier) `:` [IDENTIFIER](#identifier) - -A *typedef* field defines a field taking as value either an [enum](#enum), [struct](#struct), -[checksum](#checksum) or a [custom_field](#custom-field). - -``` -packet LastTimeModification { - coffee: Coffee, - addition: CoffeeAddition -} -``` - -### Array {#fields-array} - -> array_field:\ -> [IDENTIFIER](#identifier) `:` [INTEGER](#integer) | [IDENTIFIER](#identifier) `[`\ -> [SIZE_MODIFIER](#size-modifier) | [INTEGER](#integer)\ -> `]` - -An *array* field defines a sequence of `N` elements of type `T`. - -`N` can be: -- An [integer](#integer) value. -- A [size modifier](#size-modifier). -- Unspecified: In this case the array is dynamically sized using a -[*\_size\_*](#fields-size) or a [*\_count\_*](#fields-count). - -`T` can be: -- An [integer](#integer) denoting the bit size of one element. -- An [identifier](#identifier) referencing an [enum](#enum), a [struct](#struct) -or a [custom field](#custom-field) type. - -The size of `T` must always be a multiple of 8 bits, that is, the array elements -must start at byte boundaries. - -``` -packet Brew { - pots: 8[2], - additions: CoffeeAddition[2], - extra_additions: CoffeeAddition[], -} -``` - -### Group {#fields-group} - -> group_field:\ -> [IDENTIFIER](#identifier) (`{` [constraint_list](#constraints) `}`)? - -A *group* field inlines all the fields defined in the referenced group. - -If a [constraint list](#constraints) constrains a [scalar](#fields-scalar) field -or [typedef](#fields-typedef) field with an [enum](#enum) type, the field will -become a [fixed](#fields-fixed) field. -The [fixed](#fields-fixed) field inherits the type or size of the original field and the -value from the constraint list. - -See [Group Declaration](#group) for more information. - -### Size {#fields-size} - -> size_field:\ -> `_size_` `(` [IDENTIFIER](#identifier) | `_payload_` | `_body_` `)` `:` [INTEGER](#integer) - -A *\_size\_* field is a [scalar](#fields-scalar) field with as value the size in octet of the designated -[array](#fields-array), [*\_payload\_*](#fields-payload) or [*\_body\_*](#fields-body). - -``` -packet Parent { - _size_(_payload_): 2, - _payload_ -} - -packet Brew { - pot: 8, - _size_(additions): 8, - additions: CoffeeAddition[] -} -``` - -### Count {#fields-count} - -> count_field:\ -> `_count_` `(` [IDENTIFIER](#identifier) `)` `:` [INTEGER](#integer) - -A *\_count\_* field is a [*scalar*](#fields-scalar) field with as value the number of elements of the designated -[array](#fields-array). - -``` -packet Brew { - pot: 8, - _count_(additions): 8, - additions: CoffeeAddition[] -} -``` - -### Payload {#fields-payload} - -> payload_field:\ -> `_payload_` (`:` `[` [SIZE_MODIFIER](#size-modifier) `]` )? - -A *\_payload\_* field is a dynamically sized array of octets. - -It declares where to parse the definition of a child [packet](#packet) or [struct](#struct). - -A [*\_size\_*](#fields-size) or a [*\_count\_*](#fields-count) field referencing -the payload induce its size. - -If used, a [size modifier](#size-modifier) can alter the octet size. - -### Body {#fields-body} - -> body_field:\ -> `_body_` - -A *\_body\_* field is like a [*\_payload\_*](#fields-payload) field with the following differences: -- The body field is private to the packet definition, it's accessible only when inheriting. -- The body does not accept a size modifier. - -### Fixed {#fields-fixed} - -> fixed_field:\ -> `_fixed_` `=` \ -> ( [INTEGER](#integer) `:` [INTEGER](#integer) ) |\ -> ( [IDENTIFIER](#identifier) `:` [IDENTIFIER](#identifier) ) - -A *\_fixed\_* field defines a constant with a known bit size. -The constant can be either: -- An [integer](#integer) value -- An [enum](#enum) tag - -``` -packet Teapot { - _fixed_ = 42: 8, - _fixed_ = Empty: CoffeeAddition -} -``` - -### Checksum {#fields-checksum} - -> checksum_field:\ -> `_checksum_start_` `(` [IDENTIFIER](#identifier) `)` - -A *\_checksum_start\_* field is a zero sized field that acts as a marker for the beginning of -the fields covered by a checksum. - -The *\_checksum_start\_* references a [typedef](#fields-typedef) field -with a [checksum](#checksum) type that stores the checksum value and selects the algorithm -for the checksum. - -``` -checksum CRC16: 16 "crc16" - -packet CRCedBrew { - crc: CRC16, - _checksum_start_(crc), - pot: 8, -} -``` - -### Padding {#fields-padding} - -> padding_field:\ -> `_padding_` `[` [INTEGER](#integer) `]` - -A *\_padding\_* field immediately following an array field pads the array field with `0`s to the -specified number of **octets**. - -``` -packet PaddedCoffee { - additions: CoffeeAddition[], - _padding_[100] -} -``` - -### Reserved {#fields-reserved} - -> reserved_field:\ -> `_reserved_` `:` [INTEGER](#integer) - -A *\_reserved\_* field adds reserved bits. - -``` -packet DeloreanCoffee { - _reserved_: 2014 -} -``` - -## Tokens - -### Integer - -> INTEGER:\ -> HEXVALUE | INTVALUE -> -> HEXVALUE:\ -> `0x` | `0X` HEXDIGIT<sup>+</sup> -> -> INTVALUE:\ -> DIGIT<sup>+</sup> -> -> HEXDIGIT:\ -> DIGIT | [`a`-`f`] | [`A`-`F`] -> -> DIGIT:\ -> [`0`-`9`] - -A integer is a number in base 10 (decimal) or in base 16 (hexadecimal) with -the prefix `0x` - -### String - -> STRING:\ -> `"` (!`"` __ANY__)* `"` - -A string is sequence of character. It can be multi-line. - -### Identifier - -> IDENTIFIER: \ -> ALPHA (ALPHANUM | `_`)* -> -> ALPHA:\ -> [`a`-`z`] | [`A`-`Z`] -> -> ALPHANUM:\ -> ALPHA | DIGIT - -An identifier is a sequence of alphanumeric or `_` characters -starting with a letter. - -### Size Modifier - -> SIZE_MODIFIER:\ -> `+` INTVALUE - -A size modifier alters the octet size of the field it is attached to. -For example, `+ 2` defines that the size is 2 octet bigger than the -actual field size. - -### Comment - -> COMMENT:\ -> BLOCK_COMMENT | LINE_COMMENT -> -> BLOCK_COMMENT:\ -> `/*` (!`*/` ANY) `*/` -> -> LINE_COMMENT:\ -> `//` (!\n ANY) `//` - -### Whitespace - -> WHITESPACE:\ -> ` ` | `\t` | `\n` diff --git a/doc/rust-generated-code-guide.rst b/doc/rust-generated-code-guide.rst deleted file mode 100644 index 6dfdfd0..0000000 --- a/doc/rust-generated-code-guide.rst +++ /dev/null @@ -1,98 +0,0 @@ -Rust Generated Code Guide -========================= - -Usage ------ - -Example invocation: - -.. sourcecode:: bash - - cargo run my-protocol.pdl --output-format rust > my-protocol.rs - -Language bindings ------------------ - -This section contains the generated rust bindings for language constructs that -are stabilized. - -Preamble -^^^^^^^^ - -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. - -.. sourcecode:: rust - - #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] - pub struct Private<T>(T); - - 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 -^^^^^^^^^^^^^^^^^ - -+---------------------------------------+---------------------------------------------------------------+ -| :: | .. sourcecode:: rust | -| | | -| enum TestEnum : 8 { | #[repr(u64)] | -| A = 1, | #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] | -| B = 2, | enum TestEnum { | -| } | A = 1, | -| | B = 2, | -| | } | -| | | -| | impl TryFrom<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 { .. } | -+---------------------------------------+---------------------------------------------------------------+ -| :: | .. sourcecode:: rust | -| | | -| enum TestEnum : 8 { | #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] | -| A = 1, | enum TestEnum { | -| B = 2..10 { | A, | -| C = 3, | C, | -| }, | B(Private<u8>), | -| } | } | -| | | -| | impl TryFrom<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 { .. } | -+---------------------------------------+---------------------------------------------------------------+ -| :: | .. 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/examples/jpeg.pdl b/examples/jpeg.pdl deleted file mode 100644 index 75cde23..0000000 --- a/examples/jpeg.pdl +++ /dev/null @@ -1,88 +0,0 @@ -// Grammar file for the Jpeg File Format. -// https://www.w3.org/Graphics/JPEG/jfif3.pdf - -big_endian_packets - -enum MarkerType : 8 { - NUL = 0x00, // JPEG reserved - TEM = 0x01, // temporary marker for arithmetic coding - - // frame types - SOF0 = 0xc0, // start of frame (baseline jpeg) - SOF1 = 0xc1, // start of frame (extended sequential, huffman) - SOF2 = 0xc2, // start of frame (progressive, huffman) - SOF3 = 0xc3, // start of frame (lossless, huffman) libjpeg-unsupported - SOF5 = 0xc5, // start of frame (differential sequential, huffman) libjpeg-unsupported - SOF6 = 0xc6, // start of frame (differential progressive, huffman) libjpeg-unsupported - SOF7 = 0xc7, // start of frame (differential lossless, huffman) libjpeg-unsupported - SOF9 = 0xc9, // start of frame (extended sequential, arithmetic) - SOF10 = 0xca, // start of frame (progressive, arithmetic) - SOF11 = 0xcb, // start of frame (lossless, arithmetic) libjpeg-unsupported - SOF13 = 0xcd, // start of frame (differential sequential, arithmetic) libjpeg-unsupported - SOF14 = 0xce, // start of frame (differential progressive, arithmetic) libjpeg-unsupported - SOF15 = 0xcf, // start of frame (differential lossless, arithmetic) libjpeg-unsupported - - DHT = 0xc4, // define huffman tables - JPG = 0xc8, // reserved for JPEG extension libjpeg-unsupported - DAC = 0xcc, // define arithmetic coding conditioning libjpeg-skipped - - // restart markers (parameterless), only in scans data - RST = 0xd0..0xd7, - - // delimiters - SOI = 0xd8, // start of image (parameterless) - EOI = 0xd9, // end of image (parameterless) - SOS = 0xda, // start of scan - DQT = 0xdb, // define quantization table(s) - DNL = 0xdc, // define number of lines # libjpeg-skipped - DRI = 0xdd, // define restart interval - DHP = 0xde, // define hierarchical progression - EXP = 0xdf, // expand reference components - COM = 0xfe, // extension data (comment) - - // application segments - APP0 = 0xe0, // application segment 0 (JFIF (len >=14) / JFXX (len >= 6) / AVI MJPEG) - APP1 = 0xe1, // application segment 1 (EXIF/XMP/XAP ?) - APP2 = 0xe2, // application segment 2 (FlashPix / ICC) - APP3 = 0xe3, // application segment 3 (Kodak/...) - APP4 = 0xe4, // application segment 4 (FlashPix/...) - APP5 = 0xe5, // application segment 5 (Ricoh...) - APP6 = 0xe6, // application segment 6 (GoPro...) - APP7 = 0xe7, // application segment 7 (Pentax/Qualcomm) - APP8 = 0xe8, // application segment 8 (Spiff) - APP9 = 0xe9, // application segment 9 (MediaJukebox) - APP10 = 0xea, // application segment 10 (PhotoStudio) - APP11 = 0xeb, // application segment 11 (HDR) - APP12 = 0xec, // application segment 12 (photoshoP ducky / savE foR web) - APP13 = 0xed, // application segment 13 (photoshoP savE As) - APP14 = 0xee, // application segment 14 ("adobe" (length = 12)) - APP15 = 0xef, // application segment 15 (GraphicConverter) -} - -struct Marker { - _fixed_ = 0xff : 8, - type: MarkerType, - _payload_, -} - -struct Segment: Marker { - _size_(_payload_): 16, - _payload_ [+2], -} - -struct StartOfImage : Marker(type = SOI) {} -struct EndOfImage : Marker(type = EOI) {} - -packet Image { - start: StartOfImage, - segments: Segment[], - // The payload contains the Entropy-Coded Segment, which doesn't follow any - // similar convention despite the same segment name. They represent most of - // the file's data. Its length is unknown in advance, nor defined in the - // file. The only way to get its length is to either decode it or to - // fast-forward over it: just scan forward for a FF byte. - // If it's a restart marker (followed by D0 - D7) or a data FF - // (followed by 00), continue. - _payload_, - end: EndOfImage, -} diff --git a/examples/pcap.pdl b/examples/pcap.pdl deleted file mode 100644 index a40c0b0..0000000 --- a/examples/pcap.pdl +++ /dev/null @@ -1,27 +0,0 @@ -// Grammar file for the Libpcap File Format. -// https://wiki.wireshark.org/Development/LibpcapFileFormat - -little_endian_packets - -struct PcapHeader { - _fixed_ = 0xa1b2c3d4: 32, /* magic number */ - version_major: 16, - version_minor: 16, - thiszone: 32, /* GMT to local correction */ - sigfigs: 32, /* accuracy of timestamps */ - snaplen: 32, /* max length of captured packets, in octets */ - network: 32, /* data link type */ -} - -struct PcapRecord { - ts_sec: 32, /* timestamp seconds */ - ts_usec: 32, /* timestamp microseconds */ - _size_(_payload_): 32, /* number of octets of packet saved in file */ - orig_len: 32, /* actual length of packet */ - _payload_, /* packet octets */ -} - -packet PcapFile { - header: PcapHeader, - records: PcapRecord[], -} diff --git a/rustfmt.toml b/rustfmt.toml deleted file mode 100644 index 7b16ab7..0000000 --- a/rustfmt.toml +++ /dev/null @@ -1,8 +0,0 @@ -# Android Format Style -# -# Copied from Android: -# https://cs.android.com/android/platform/superproject/+/master:packages/modules/Bluetooth/rustfmt.toml. - -edition = "2021" -use_small_heuristics = "Max" -newline_style = "Unix" diff --git a/scripts/generate_cxx_backend.py b/scripts/generate_cxx_backend.py index 4937079..d3abb39 100755 --- a/scripts/generate_cxx_backend.py +++ b/scripts/generate_cxx_backend.py @@ -817,7 +817,9 @@ def generate_enum_declaration(decl: ast.EnumDeclaration) -> str: enum_type = get_cxx_scalar_type(decl.width) tag_decls = [] for t in decl.tags: - tag_decls.append(f"{t.id} = {hex(t.value)},") + # Exclude default tags: DEFAULT = .. + if t.value is not None: + tag_decls.append(f"{t.id} = {hex(t.value)},") return dedent("""\ @@ -833,7 +835,9 @@ def generate_enum_to_text(decl: ast.EnumDeclaration) -> str: enum_name = decl.id tag_cases = [] for t in decl.tags: - tag_cases.append(f"case {enum_name}::{t.id}: return \"{t.id}\";") + # Exclude default tags: DEFAULT = .. + if t.value is not None: + tag_cases.append(f"case {enum_name}::{t.id}: return \"{t.id}\";") return dedent("""\ @@ -1654,7 +1658,7 @@ def generate_struct_declaration(struct: ast.StructDeclaration) -> str: def run(input: argparse.FileType, output: argparse.FileType, namespace: Optional[str], include_header: List[str], - using_namespace: List[str]): + using_namespace: List[str], exclude_declaration: List[str]): file = ast.File.from_json(json.load(input)) core.desugar(file) @@ -1664,28 +1668,6 @@ def run(input: argparse.FileType, output: argparse.FileType, namespace: Optional open_namespace = f"namespace {namespace} {{" if namespace else "" close_namespace = f"}} // {namespace}" if namespace else "" - # Disable unsupported features in the canonical test suite. - skipped_decls = [ - 'Packet_Custom_Field_ConstantSize', - 'Packet_Custom_Field_VariableSize', - 'Packet_Checksum_Field_FromStart', - 'Packet_Checksum_Field_FromEnd', - 'Struct_Custom_Field_ConstantSize', - 'Struct_Custom_Field_VariableSize', - 'Struct_Checksum_Field_FromStart', - 'Struct_Checksum_Field_FromEnd', - 'Struct_Custom_Field_ConstantSize_', - 'Struct_Custom_Field_VariableSize_', - 'Struct_Checksum_Field_FromStart_', - 'Struct_Checksum_Field_FromEnd_', - 'PartialParent5', - 'PartialChild5_A', - 'PartialChild5_B', - 'PartialParent12', - 'PartialChild12_A', - 'PartialChild12_B', - ] - output.write( dedent("""\ // File generated from {input_name}, with the command: @@ -1728,7 +1710,7 @@ def run(input: argparse.FileType, output: argparse.FileType, namespace: Optional output.write(f"class {d.id}View;\n") for d in file.declarations: - if d.id in skipped_decls: + if d.id in exclude_declaration: continue if isinstance(d, ast.EnumDeclaration): @@ -1755,6 +1737,11 @@ def main() -> int: default=[], action='append', help='Added using namespace statements') + parser.add_argument('--exclude-declaration', + type=str, + default=[], + action='append', + help='Exclude declaration from the generated output') return run(**vars(parser.parse_args())) diff --git a/scripts/generate_cxx_backend_tests.py b/scripts/generate_cxx_backend_tests.py index 818d376..d8ddd44 100755 --- a/scripts/generate_cxx_backend_tests.py +++ b/scripts/generate_cxx_backend_tests.py @@ -328,6 +328,10 @@ def run(input: argparse.FileType, output: argparse.FileType, test_vectors: argpa 'Struct_Checksum_Field_FromEnd', 'PartialParent5', 'PartialParent12', + 'Packet_Array_Field_VariableElementSize_ConstantSize', + 'Packet_Array_Field_VariableElementSize_VariableSize', + 'Packet_Array_Field_VariableElementSize_VariableCount', + 'Packet_Array_Field_VariableElementSize_UnknownSize', ] output.write( diff --git a/scripts/generate_python_backend.py b/scripts/generate_python_backend.py index 8938173..a3a06de 100755 --- a/scripts/generate_python_backend.py +++ b/scripts/generate_python_backend.py @@ -33,7 +33,7 @@ def mask(width: int) -> str: def generate_prelude() -> str: return dedent("""\ from dataclasses import dataclass, field, fields - from typing import Optional, List, Tuple + from typing import Optional, List, Tuple, Union import enum import inspect import math @@ -412,7 +412,7 @@ class FieldParser: self.unchecked_append_(f"if {v} != {hex(field.value)}:") self.unchecked_append_(f" raise Exception('Unexpected fixed field value')") elif isinstance(field, ast.TypedefField): - self.unchecked_append_(f"fields['{field.id}'] = {field.type_id}({v})") + self.unchecked_append_(f"fields['{field.id}'] = {field.type_id}.from_int({v})") elif isinstance(field, ast.SizeField): self.unchecked_append_(f"{field.field_id}_size = {v}") elif isinstance(field, ast.CountField): @@ -1012,17 +1012,37 @@ def generate_enum_declaration(decl: ast.EnumDeclaration) -> str: enum_name = decl.id tag_decls = [] for t in decl.tags: + # Enums in python are closed and ranges cannot be represented; + # instead the generated code uses Union[int, Enum] + # when ranges are used. if t.value is not None: tag_decls.append(f"{t.id} = {hex(t.value)}") - if t.range is not None: - tag_decls.append(f"{t.id}_START = {hex(t.range[0])}") - tag_decls.append(f"{t.id}_END = {hex(t.range[1])}") + + if core.is_open_enum(decl): + unknown_handler = ["return v"] + else: + unknown_handler = [] + for t in decl.tags: + if t.range is not None: + unknown_handler.append(f"if v >= 0x{t.range[0]:x} and v <= 0x{t.range[1]:x}:") + unknown_handler.append(f" return v") + unknown_handler.append("raise exn") return dedent("""\ class {enum_name}(enum.IntEnum): {tag_decls} - """).format(enum_name=enum_name, tag_decls=indent(tag_decls, 1)) + + @staticmethod + def from_int(v: int) -> Union[int, '{enum_name}']: + try: + return {enum_name}(v) + except ValueError as exn: + {unknown_handler} + + """).format(enum_name=enum_name, + tag_decls=indent(tag_decls, 1), + unknown_handler=indent(unknown_handler, 3)) def generate_packet_declaration(packet: ast.Declaration) -> str: @@ -1047,7 +1067,10 @@ def generate_packet_declaration(packet: ast.Declaration) -> str: elif isinstance(f, ast.ScalarField): field_decls.append(f"{f.id}: int = field(kw_only=True, default=0)") elif isinstance(f, ast.TypedefField): - if isinstance(f.type, ast.EnumDeclaration): + if isinstance(f.type, ast.EnumDeclaration) and f.type.tags[0].range: + field_decls.append( + f"{f.id}: {f.type_id} = field(kw_only=True, default={f.type.tags[0].range[0]})") + elif isinstance(f.type, ast.EnumDeclaration): field_decls.append( f"{f.id}: {f.type_id} = field(kw_only=True, default={f.type_id}.{f.type.tags[0].id})") elif isinstance(f.type, ast.ChecksumDeclaration): @@ -1134,13 +1157,16 @@ def generate_checksum_declaration_check(decl: ast.ChecksumDeclaration) -> str: """).format(checksum_name=decl.id) -def run(input: argparse.FileType, output: argparse.FileType, custom_type_location: Optional[str]): +def run(input: argparse.FileType, output: argparse.FileType, custom_type_location: Optional[str], exclude_declaration: List[str]): file = ast.File.from_json(json.load(input)) core.desugar(file) custom_types = [] custom_type_checks = "" for d in file.declarations: + if d.id in exclude_declaration: + continue + if isinstance(d, ast.CustomFieldDeclaration): custom_types.append(d.id) custom_type_checks += generate_custom_field_declaration_check(d) @@ -1157,6 +1183,9 @@ def run(input: argparse.FileType, output: argparse.FileType, custom_type_locatio output.write(custom_type_checks) for d in file.declarations: + if d.id in exclude_declaration: + continue + if isinstance(d, ast.EnumDeclaration): output.write(generate_enum_declaration(d)) elif isinstance(d, (ast.PacketDeclaration, ast.StructDeclaration)): @@ -1172,6 +1201,11 @@ def main() -> int: type=str, required=False, help='Module of declaration of custom types') + parser.add_argument('--exclude-declaration', + type=str, + default=[], + action='append', + help='Exclude declaration from the generated output') return run(**vars(parser.parse_args())) diff --git a/scripts/pdl/ast.py b/scripts/pdl/ast.py index 5ade0fa..341fac5 100644 --- a/scripts/pdl/ast.py +++ b/scripts/pdl/ast.py @@ -87,6 +87,12 @@ class SizeField(Field): width: int +@node('elementsize_field') +class ElementSize(Field): + field_id: str + width: int + + @node('count_field') class CountField(Field): field_id: str @@ -276,6 +282,8 @@ def convert_(obj: object) -> object: loc = obj['loc'] loc = SourceRange(loc['file'], SourceLocation(**loc['start']), SourceLocation(**loc['end'])) constructor = constructors_.get(kind) + if not constructor: + raise Exception(f'Unknown kind {kind}') members = {'loc': loc, 'kind': kind} cond = None for name, value in obj.items(): diff --git a/scripts/pdl/core.py b/scripts/pdl/core.py index 5ddbb02..27da56b 100644 --- a/scripts/pdl/core.py +++ b/scripts/pdl/core.py @@ -360,3 +360,9 @@ def is_bit_field(field: Field) -> bool: else: return False + +def is_open_enum(decl: EnumDeclaration) -> bool: + """Return true if the enum declaration is open, i.e. contains a tag + declaration of the form DEFAULT = ..""" + + return any(t.value is None for t in decl.tags) diff --git a/src/analyzer.rs b/src/analyzer.rs index b80a6b6..90ed239 100644 --- a/src/analyzer.rs +++ b/src/analyzer.rs @@ -19,128 +19,70 @@ use codespan_reporting::term::termcolor; use std::collections::HashMap; use crate::ast::*; -use crate::parser::ast as parser_ast; - -pub mod ast { - use serde::Serialize; - - /// Field and declaration size information. - #[derive(Debug, Clone, Copy, PartialEq, Eq)] - #[allow(unused)] - pub enum Size { - /// Constant size in bits. - Static(usize), - /// Size indicated at packet parsing by a size or count field. - /// The parameter is the static part of the size. - Dynamic, - /// The size cannot be determined statically or at runtime. - /// The packet assumes the largest possible size. - Unknown, - } - - // TODO: use derive(Default) when UWB is using Rust 1.62.0. - #[allow(clippy::derivable_impls)] - impl Default for Size { - fn default() -> Size { - Size::Unknown - } - } - - #[derive(Debug, Serialize, Default, Clone, PartialEq)] - pub struct Annotation; - - #[derive(Default, Debug, Clone, PartialEq, Eq)] - pub struct FieldAnnotation { - // Size of field. - pub size: Size, - // Size of field with padding bytes. - // This information exists only for array fields. - pub padded_size: Option<usize>, - } - - #[derive(Default, Debug, Clone, PartialEq, Eq)] - pub struct DeclAnnotation { - // Size computed excluding the payload. - pub size: Size, - // Payload size, or Static(0) if the declaration does not - // have a payload. - pub payload_size: Size, - } - - impl std::ops::Add for Size { - type Output = Size; - fn add(self, rhs: Size) -> Self::Output { - match (self, rhs) { - (Size::Unknown, _) | (_, Size::Unknown) => Size::Unknown, - (Size::Dynamic, _) | (_, Size::Dynamic) => Size::Dynamic, - (Size::Static(lhs), Size::Static(rhs)) => Size::Static(lhs + rhs), - } - } - } - impl std::ops::Mul for Size { - type Output = Size; - fn mul(self, rhs: Size) -> Self::Output { - match (self, rhs) { - (Size::Unknown, _) | (_, Size::Unknown) => Size::Unknown, - (Size::Dynamic, _) | (_, Size::Dynamic) => Size::Dynamic, - (Size::Static(lhs), Size::Static(rhs)) => Size::Static(lhs * rhs), - } - } - } +/// Field and declaration size information. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[allow(unused)] +pub enum Size { + /// Constant size in bits. + Static(usize), + /// Size indicated at packet parsing by a size or count field. + /// The parameter is the static part of the size. + Dynamic, + /// The size cannot be determined statically or at runtime. + /// The packet assumes the largest possible size. + Unknown, +} - impl std::ops::Mul<usize> for Size { - type Output = Size; - fn mul(self, rhs: usize) -> Self::Output { - match self { - Size::Unknown => Size::Unknown, - Size::Dynamic => Size::Dynamic, - Size::Static(lhs) => Size::Static(lhs * rhs), - } - } +// TODO: use derive(Default) when UWB is using Rust 1.62.0. +#[allow(clippy::derivable_impls)] +impl Default for Size { + fn default() -> Size { + Size::Unknown } +} - impl Size { - // Returns the width if the size is static. - pub fn static_(&self) -> Option<usize> { - match self { - Size::Static(size) => Some(*size), - Size::Dynamic | Size::Unknown => None, - } +impl std::ops::Add for Size { + type Output = Size; + fn add(self, rhs: Size) -> Self::Output { + match (self, rhs) { + (Size::Unknown, _) | (_, Size::Unknown) => Size::Unknown, + (Size::Dynamic, _) | (_, Size::Dynamic) => Size::Dynamic, + (Size::Static(lhs), Size::Static(rhs)) => Size::Static(lhs + rhs), } } +} - impl DeclAnnotation { - pub fn total_size(&self) -> Size { - self.size + self.payload_size +impl std::ops::Mul for Size { + type Output = Size; + fn mul(self, rhs: Size) -> Self::Output { + match (self, rhs) { + (Size::Unknown, _) | (_, Size::Unknown) => Size::Unknown, + (Size::Dynamic, _) | (_, Size::Dynamic) => Size::Dynamic, + (Size::Static(lhs), Size::Static(rhs)) => Size::Static(lhs * rhs), } } +} - impl FieldAnnotation { - pub fn new(size: Size) -> Self { - FieldAnnotation { size, padded_size: None } - } - - // Returns the field width or padded width if static. - pub fn static_(&self) -> Option<usize> { - match self.padded_size { - Some(padding) => Some(8 * padding), - None => self.size.static_(), - } +impl std::ops::Mul<usize> for Size { + type Output = Size; + fn mul(self, rhs: usize) -> Self::Output { + match self { + Size::Unknown => Size::Unknown, + Size::Dynamic => Size::Dynamic, + Size::Static(lhs) => Size::Static(lhs * rhs), } } +} - impl crate::ast::Annotation for Annotation { - type FieldAnnotation = FieldAnnotation; - type DeclAnnotation = DeclAnnotation; +impl Size { + // Returns the width if the size is static. + pub fn static_(&self) -> Option<usize> { + match self { + Size::Static(size) => Some(*size), + Size::Dynamic | Size::Unknown => None, + } } - - #[allow(unused)] - pub type Field = crate::ast::Field<Annotation>; - #[allow(unused)] - pub type Decl = crate::ast::Decl<Annotation>; - #[allow(unused)] - pub type File = crate::ast::File<Annotation>; } /// List of unique errors reported as analyzer diagnostics. @@ -212,12 +154,21 @@ pub struct Diagnostics { /// Gather information about the full AST. #[derive(Debug)] -pub struct Scope<'d, A: Annotation = ast::Annotation> { +pub struct Scope<'d> { /// Reference to the source file. - pub file: &'d crate::ast::File<A>, + pub file: &'d File, /// Collection of Group, Packet, Enum, Struct, Checksum, and CustomField /// declarations. - pub typedef: HashMap<String, &'d crate::ast::Decl<A>>, + pub typedef: HashMap<String, &'d Decl>, +} + +/// Gather size information about the full AST. +#[derive(Debug)] +pub struct Schema { + decl_size: HashMap<DeclKey, Size>, + field_size: HashMap<FieldKey, Size>, + padded_size: HashMap<FieldKey, Option<usize>>, + payload_size: HashMap<DeclKey, Size>, } impl Diagnostics { @@ -250,10 +201,10 @@ impl Diagnostics { } } -impl<'d, A: Annotation + Default> Scope<'d, A> { - pub fn new(file: &'d crate::ast::File<A>) -> Result<Scope<'d, A>, Diagnostics> { +impl<'d> Scope<'d> { + pub fn new(file: &'d File) -> Result<Scope<'d>, Diagnostics> { // Gather top-level declarations. - let mut scope: Scope<A> = Scope { file, typedef: Default::default() }; + let mut scope: Scope = Scope { file, typedef: Default::default() }; let mut diagnostics: Diagnostics = Default::default(); for decl in &file.declarations { if let Some(id) = decl.id() { @@ -286,24 +237,18 @@ 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 { + pub fn iter_children<'s>(&'s self, decl: &'d Decl) -> impl Iterator<Item = &'d Decl> + '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>> { + pub fn get_parent(&self, decl: &Decl) -> Option<&'d Decl> { decl.parent_id().and_then(|parent_id| self.typedef.get(parent_id).cloned()) } /// Iterate over the parent declarations of the selected declaration. - pub fn iter_parents<'s>( - &'s self, - decl: &'d crate::ast::Decl<A>, - ) -> impl Iterator<Item = &'d Decl<A>> + 's { + pub fn iter_parents<'s>(&'s self, decl: &'d Decl) -> impl Iterator<Item = &'d Decl> + 's { std::iter::successors(self.get_parent(decl), |decl| self.get_parent(decl)) } @@ -311,24 +256,21 @@ impl<'d, A: Annotation + Default> Scope<'d, A> { /// 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 { + decl: &'d Decl, + ) -> impl Iterator<Item = &'d Decl> + '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, - decl: &'d crate::ast::Decl<A>, - ) -> impl Iterator<Item = &'d Field<A>> + 's { + pub fn iter_fields<'s>(&'s self, decl: &'d Decl) -> impl Iterator<Item = &'d Field> + 's { 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 { + decl: &'d Decl, + ) -> impl Iterator<Item = &'d Field> + 's { std::iter::successors(self.get_parent(decl), |decl| self.get_parent(decl)) .flat_map(Decl::fields) } @@ -336,16 +278,13 @@ impl<'d, A: Annotation + Default> Scope<'d, A> { /// Iterate over the declaration and its parent's constraints. pub fn iter_constraints<'s>( &'s self, - decl: &'d crate::ast::Decl<A>, + decl: &'d Decl, ) -> 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( - &self, - field: &crate::ast::Field<A>, - ) -> Option<&'d crate::ast::Decl<A>> { + pub fn get_type_declaration(&self, field: &Field) -> Option<&'d Decl> { match &field.desc { FieldDesc::Checksum { .. } | FieldDesc::Padding { .. } @@ -367,7 +306,7 @@ impl<'d, A: Annotation + Default> Scope<'d, A> { } /// Test if the selected field is a bit-field. - pub fn is_bitfield(&self, field: &crate::ast::Field<A>) -> bool { + pub fn is_bitfield(&self, field: &Field) -> bool { match &field.desc { FieldDesc::Size { .. } | FieldDesc::Count { .. } @@ -386,6 +325,173 @@ impl<'d, A: Annotation + Default> Scope<'d, A> { } } +impl Schema { + /// Check correct definition of packet sizes. + /// Annotate fields and declarations with the size in bits. + pub fn new(file: &File) -> Schema { + fn annotate_decl(schema: &mut Schema, scope: &HashMap<String, DeclKey>, decl: &Decl) { + // Compute the padding size for each field. + let mut padding = None; + for field in decl.fields().rev() { + schema.padded_size.insert(field.key, padding); + padding = match &field.desc { + FieldDesc::Padding { size } => Some(8 * *size), + _ => None, + }; + } + + let mut size = decl + .parent_id() + .and_then(|parent_id| scope.get(parent_id)) + .map(|key| schema.decl_size(*key)) + .unwrap_or(Size::Static(0)); + let mut payload_size = Size::Static(0); + + for field in decl.fields() { + // Compute the size of each declared fields. + let field_size = annotate_field(schema, scope, decl, field); + + // Sum the size of the non payload fields to get the + // declaration size. Lookup the payload field size. + match &field.desc { + FieldDesc::Payload { .. } | FieldDesc::Body { .. } => payload_size = field_size, + _ => { + size = size + + match schema.padded_size.get(&field.key).unwrap() { + Some(padding) => Size::Static(*padding), + None => field_size, + } + } + } + } + + // Save the declaration size. + let (size, payload_size) = match &decl.desc { + DeclDesc::Packet { .. } | DeclDesc::Struct { .. } | DeclDesc::Group { .. } => { + (size, payload_size) + } + DeclDesc::Enum { width, .. } + | DeclDesc::Checksum { width, .. } + | DeclDesc::CustomField { width: Some(width), .. } => { + (Size::Static(*width), Size::Static(0)) + } + DeclDesc::CustomField { width: None, .. } => (Size::Dynamic, Size::Static(0)), + DeclDesc::Test { .. } => (Size::Static(0), Size::Static(0)), + }; + + schema.decl_size.insert(decl.key, size); + schema.payload_size.insert(decl.key, payload_size); + } + + fn annotate_field( + schema: &mut Schema, + scope: &HashMap<String, DeclKey>, + decl: &Decl, + field: &Field, + ) -> Size { + let size = match &field.desc { + _ if field.cond.is_some() => Size::Dynamic, + FieldDesc::Checksum { .. } | FieldDesc::Padding { .. } => Size::Static(0), + FieldDesc::Size { width, .. } + | FieldDesc::Count { width, .. } + | FieldDesc::ElementSize { width, .. } + | FieldDesc::FixedScalar { width, .. } + | FieldDesc::Reserved { width } + | FieldDesc::Scalar { width, .. } => Size::Static(*width), + FieldDesc::Flag { .. } => Size::Static(1), + FieldDesc::Body | FieldDesc::Payload { .. } => { + let has_payload_size = decl.fields().any(|field| match &field.desc { + FieldDesc::Size { field_id, .. } => { + field_id == "_body_" || field_id == "_payload_" + } + _ => false, + }); + if has_payload_size { + Size::Dynamic + } else { + Size::Unknown + } + } + FieldDesc::Typedef { type_id, .. } + | FieldDesc::FixedEnum { enum_id: type_id, .. } + | FieldDesc::Group { group_id: type_id, .. } => { + let type_key = scope.get(type_id).unwrap(); + schema.total_size(*type_key) + } + FieldDesc::Array { width: Some(width), size: Some(size), .. } => { + Size::Static(*size * *width) + } + FieldDesc::Array { + width: None, size: Some(size), type_id: Some(type_id), .. + } => { + let type_key = scope.get(type_id).unwrap(); + schema.total_size(*type_key) * *size + } + FieldDesc::Array { id, size: None, .. } => { + // The element does not matter when the size of the array is + // not static. The array size depends on there being a count + // or size field or not. + let has_array_size = decl.fields().any(|field| match &field.desc { + FieldDesc::Size { field_id, .. } | FieldDesc::Count { field_id, .. } => { + field_id == id + } + _ => false, + }); + if has_array_size { + Size::Dynamic + } else { + Size::Unknown + } + } + FieldDesc::Array { .. } => unreachable!(), + }; + + schema.field_size.insert(field.key, size); + size + } + + let mut scope = HashMap::new(); + for decl in &file.declarations { + if let Some(id) = decl.id() { + scope.insert(id.to_owned(), decl.key); + } + } + + let mut schema = Schema { + field_size: Default::default(), + decl_size: Default::default(), + padded_size: Default::default(), + payload_size: Default::default(), + }; + + for decl in &file.declarations { + annotate_decl(&mut schema, &scope, decl); + } + + schema + } + + pub fn field_size(&self, key: FieldKey) -> Size { + *self.field_size.get(&key).unwrap() + } + + pub fn decl_size(&self, key: DeclKey) -> Size { + *self.decl_size.get(&key).unwrap() + } + + pub fn padded_size(&self, key: FieldKey) -> Option<usize> { + *self.padded_size.get(&key).unwrap() + } + + pub fn payload_size(&self, key: DeclKey) -> Size { + *self.payload_size.get(&key).unwrap() + } + + pub fn total_size(&self, key: DeclKey) -> Size { + self.decl_size(key) + self.payload_size(key) + } +} + /// Return the bit-width of a scalar value. fn bit_width(value: usize) -> usize { usize::BITS as usize - value.leading_zeros() as usize @@ -411,10 +517,7 @@ fn scalar_max(width: usize) -> usize { /// - undeclared test identifier /// - invalid test identifier /// - recursive declaration -fn check_decl_identifiers( - file: &parser_ast::File, - scope: &Scope<parser_ast::Annotation>, -) -> Result<(), Diagnostics> { +fn check_decl_identifiers(file: &File, scope: &Scope) -> Result<(), Diagnostics> { enum Mark { Temporary, Permanent, @@ -425,9 +528,9 @@ fn check_decl_identifiers( } fn bfs<'d>( - decl: &'d parser_ast::Decl, + decl: &'d Decl, context: &mut Context<'d>, - scope: &Scope<'d, parser_ast::Annotation>, + scope: &Scope<'d>, diagnostics: &mut Diagnostics, ) { let decl_id = decl.id().unwrap(); @@ -586,7 +689,7 @@ fn check_decl_identifiers( /// Check field identifiers. /// Raises error diagnostics for the following cases: /// - duplicate field identifier -fn check_field_identifiers(file: &parser_ast::File) -> Result<(), Diagnostics> { +fn check_field_identifiers(file: &File) -> Result<(), Diagnostics> { let mut diagnostics: Diagnostics = Default::default(); for decl in &file.declarations { let mut local_scope = HashMap::new(); @@ -620,7 +723,7 @@ fn check_field_identifiers(file: &parser_ast::File) -> Result<(), Diagnostics> { /// Raises error diagnostics for the following cases: /// - duplicate tag identifier /// - duplicate tag value -fn check_enum_declarations(file: &parser_ast::File) -> Result<(), Diagnostics> { +fn check_enum_declarations(file: &File) -> Result<(), Diagnostics> { // Return the inclusive range with bounds correctly ordered. // The analyzer will raise an error if the bounds are incorrectly ordered, but this // will enable additional checks. @@ -855,8 +958,8 @@ fn check_enum_declarations(file: &parser_ast::File) -> Result<(), Diagnostics> { /// Helper function for validating one constraint. fn check_constraint( constraint: &Constraint, - decl: &parser_ast::Decl, - scope: &Scope<parser_ast::Annotation>, + decl: &Decl, + scope: &Scope, diagnostics: &mut Diagnostics, ) { match scope.iter_fields(decl).find(|field| field.id() == Some(&constraint.id)) { @@ -985,8 +1088,8 @@ fn check_constraint( /// Helper function for validating a list of constraints. fn check_constraints_list<'d>( constraints: &'d [Constraint], - parent_decl: &parser_ast::Decl, - scope: &Scope<parser_ast::Annotation>, + parent_decl: &Decl, + scope: &Scope, mut constraints_by_id: HashMap<String, &'d Constraint>, diagnostics: &mut Diagnostics, ) { @@ -1018,10 +1121,7 @@ fn check_constraints_list<'d>( /// - invalid constraint enum value (bad type) /// - invalid constraint enum value (undeclared tag) /// - duplicate constraint -fn check_decl_constraints( - file: &parser_ast::File, - scope: &Scope<parser_ast::Annotation>, -) -> Result<(), Diagnostics> { +fn check_decl_constraints(file: &File, scope: &Scope) -> Result<(), Diagnostics> { let mut diagnostics: Diagnostics = Default::default(); for decl in &file.declarations { // Check constraints for packet inheritance. @@ -1060,10 +1160,7 @@ fn check_decl_constraints( /// - invalid constraint enum value (bad type) /// - invalid constraint enum value (undeclared tag) /// - duplicate constraint -fn check_group_constraints( - file: &parser_ast::File, - scope: &Scope<parser_ast::Annotation>, -) -> Result<(), Diagnostics> { +fn check_group_constraints(file: &File, scope: &Scope) -> Result<(), Diagnostics> { let mut diagnostics: Diagnostics = Default::default(); for decl in &file.declarations { // Check constraints for group inlining. @@ -1095,7 +1192,7 @@ fn check_group_constraints( /// - undeclared elementsize identifier /// - invalid elementsize identifier /// - duplicate elementsize field -fn check_size_fields(file: &parser_ast::File) -> Result<(), Diagnostics> { +fn check_size_fields(file: &File) -> Result<(), Diagnostics> { let mut diagnostics: Diagnostics = Default::default(); for decl in &file.declarations { let mut size_for_id = HashMap::new(); @@ -1223,10 +1320,7 @@ fn check_size_fields(file: &parser_ast::File) -> Result<(), Diagnostics> { /// - undeclared enum identifier /// - invalid enum identifier /// - undeclared tag identifier -fn check_fixed_fields( - file: &parser_ast::File, - scope: &Scope<parser_ast::Annotation>, -) -> Result<(), Diagnostics> { +fn check_fixed_fields(file: &File, scope: &Scope) -> Result<(), Diagnostics> { let mut diagnostics: Diagnostics = Default::default(); for decl in &file.declarations { for field in decl.fields() { @@ -1291,16 +1385,16 @@ fn check_fixed_fields( /// - duplicate body field /// - duplicate body field size /// - missing payload field -fn check_payload_fields(file: &parser_ast::File) -> Result<(), Diagnostics> { +fn check_payload_fields(file: &File) -> Result<(), Diagnostics> { // Check whether the declaration requires a payload field. // The payload is required if any child packets declares fields. - fn requires_payload(file: &parser_ast::File, decl: &parser_ast::Decl) -> bool { + fn requires_payload(file: &File, decl: &Decl) -> bool { file.iter_children(decl).any(|child| child.fields().next().is_some()) } let mut diagnostics: Diagnostics = Default::default(); for decl in &file.declarations { - let mut payload: Option<&parser_ast::Field> = None; + let mut payload: Option<&Field> = None; for field in decl.fields() { match &field.desc { FieldDesc::Payload { .. } | FieldDesc::Body { .. } => { @@ -1345,7 +1439,7 @@ fn check_payload_fields(file: &parser_ast::File) -> Result<(), Diagnostics> { /// Check array fields. /// Raises error diagnostics for the following cases: /// - redundant array field size -fn check_array_fields(file: &parser_ast::File) -> Result<(), Diagnostics> { +fn check_array_fields(file: &File) -> Result<(), Diagnostics> { let mut diagnostics: Diagnostics = Default::default(); for decl in &file.declarations { for field in decl.fields() { @@ -1379,7 +1473,7 @@ fn check_array_fields(file: &parser_ast::File) -> Result<(), Diagnostics> { /// Check padding fields. /// Raises error diagnostics for the following cases: /// - padding field not following an array field -fn check_padding_fields(file: &parser_ast::File) -> Result<(), Diagnostics> { +fn check_padding_fields(file: &File) -> Result<(), Diagnostics> { let mut diagnostics: Diagnostics = Default::default(); for decl in &file.declarations { let mut previous_is_array = false; @@ -1405,10 +1499,7 @@ fn check_padding_fields(file: &parser_ast::File) -> Result<(), Diagnostics> { /// - checksum field precedes checksum start /// - undeclared checksum field /// - invalid checksum field -fn check_checksum_fields( - _file: &parser_ast::File, - _scope: &Scope<parser_ast::Annotation>, -) -> Result<(), Diagnostics> { +fn check_checksum_fields(_file: &File, _scope: &Scope) -> Result<(), Diagnostics> { // TODO Ok(()) } @@ -1419,11 +1510,11 @@ fn check_checksum_fields( /// - invalid constraint identifier /// - invalid constraint scalar value (bad type) /// - invalid constraint scalar value (overflow) -fn check_optional_fields(file: &parser_ast::File) -> Result<(), Diagnostics> { +fn check_optional_fields(file: &File) -> Result<(), Diagnostics> { let mut diagnostics: Diagnostics = Default::default(); for decl in &file.declarations { - let mut local_scope: HashMap<String, &parser_ast::Field> = HashMap::new(); - let mut condition_ids: HashMap<String, &parser_ast::Field> = HashMap::new(); + let mut local_scope: HashMap<String, &Field> = HashMap::new(); + let mut condition_ids: HashMap<String, &Field> = HashMap::new(); for field in decl.fields() { if let Some(ref cond) = field.cond { match &field.desc { @@ -1527,167 +1618,13 @@ fn check_optional_fields(file: &parser_ast::File) -> Result<(), Diagnostics> { diagnostics.err_or(()) } -/// Check correct definition of packet sizes. -/// Annotate fields and declarations with the size in bits. -fn compute_field_sizes(file: &parser_ast::File) -> ast::File { - fn annotate_decl( - decl: &parser_ast::Decl, - scope: &HashMap<String, ast::DeclAnnotation>, - ) -> ast::Decl { - // Annotate the declaration fields. - // Add the padding information to the fields in the same pass. - let mut decl = decl.annotate(Default::default(), |fields| { - let mut fields: Vec<_> = - fields.iter().map(|field| annotate_field(decl, field, scope)).collect(); - let mut padding = None; - for field in fields.iter_mut().rev() { - field.annot.padded_size = padding; - padding = match &field.desc { - FieldDesc::Padding { size } => Some(*size), - _ => None, - }; - } - fields - }); - - // Compute the declaration annotation. - decl.annot = match &decl.desc { - DeclDesc::Packet { fields, .. } - | DeclDesc::Struct { fields, .. } - | DeclDesc::Group { fields, .. } => { - let mut size = decl - .parent_id() - .and_then(|parent_id| scope.get(parent_id)) - .map(|annot| annot.size) - .unwrap_or(ast::Size::Static(0)); - let mut payload_size = ast::Size::Static(0); - for field in fields { - match &field.desc { - FieldDesc::Payload { .. } | FieldDesc::Body { .. } => { - payload_size = field.annot.size - } - _ => { - size = size - + match field.annot.padded_size { - Some(padding) => ast::Size::Static(8 * padding), - None => field.annot.size, - } - } - } - } - ast::DeclAnnotation { size, payload_size } - } - DeclDesc::Enum { width, .. } - | DeclDesc::Checksum { width, .. } - | DeclDesc::CustomField { width: Some(width), .. } => ast::DeclAnnotation { - size: ast::Size::Static(*width), - payload_size: ast::Size::Static(0), - }, - DeclDesc::CustomField { width: None, .. } => { - ast::DeclAnnotation { size: ast::Size::Dynamic, payload_size: ast::Size::Static(0) } - } - DeclDesc::Test { .. } => ast::DeclAnnotation { - size: ast::Size::Static(0), - payload_size: ast::Size::Static(0), - }, - }; - decl - } - - fn annotate_field( - decl: &parser_ast::Decl, - field: &parser_ast::Field, - scope: &HashMap<String, ast::DeclAnnotation>, - ) -> ast::Field { - field.annotate(match &field.desc { - _ if field.cond.is_some() => ast::FieldAnnotation::new(ast::Size::Dynamic), - FieldDesc::Checksum { .. } | FieldDesc::Padding { .. } => { - ast::FieldAnnotation::new(ast::Size::Static(0)) - } - FieldDesc::Size { width, .. } - | FieldDesc::Count { width, .. } - | FieldDesc::ElementSize { width, .. } - | FieldDesc::FixedScalar { width, .. } - | FieldDesc::Reserved { width } - | FieldDesc::Scalar { width, .. } => { - ast::FieldAnnotation::new(ast::Size::Static(*width)) - } - FieldDesc::Flag { .. } => ast::FieldAnnotation::new(ast::Size::Static(1)), - FieldDesc::Body | FieldDesc::Payload { .. } => { - let has_payload_size = decl.fields().any(|field| match &field.desc { - FieldDesc::Size { field_id, .. } => { - field_id == "_body_" || field_id == "_payload_" - } - _ => false, - }); - ast::FieldAnnotation::new(if has_payload_size { - ast::Size::Dynamic - } else { - ast::Size::Unknown - }) - } - FieldDesc::Typedef { type_id, .. } - | FieldDesc::FixedEnum { enum_id: type_id, .. } - | FieldDesc::Group { group_id: type_id, .. } => { - let type_annot = scope.get(type_id).unwrap(); - ast::FieldAnnotation::new(type_annot.size + type_annot.payload_size) - } - FieldDesc::Array { width: Some(width), size: Some(size), .. } => { - ast::FieldAnnotation::new(ast::Size::Static(*size * *width)) - } - FieldDesc::Array { width: None, size: Some(size), type_id: Some(type_id), .. } => { - let type_annot = scope.get(type_id).unwrap(); - ast::FieldAnnotation::new((type_annot.size + type_annot.payload_size) * *size) - } - FieldDesc::Array { id, size: None, .. } => { - // The element does not matter when the size of the array is - // not static. The array size depends on there being a count - // or size field or not. - let has_array_size = decl.fields().any(|field| match &field.desc { - FieldDesc::Size { field_id, .. } | FieldDesc::Count { field_id, .. } => { - field_id == id - } - _ => false, - }); - ast::FieldAnnotation::new(if has_array_size { - ast::Size::Dynamic - } else { - ast::Size::Unknown - }) - } - FieldDesc::Array { .. } => unreachable!(), - }) - } - - // Construct a scope mapping typedef identifiers to decl annotations. - let mut scope = HashMap::new(); - - // Annotate declarations. - let mut declarations = Vec::new(); - for decl in file.declarations.iter() { - let decl = annotate_decl(decl, &scope); - if let Some(id) = decl.id() { - scope.insert(id.to_string(), decl.annot.clone()); - } - declarations.push(decl); - } - - File { - version: file.version.clone(), - file: file.file, - comments: file.comments.clone(), - endianness: file.endianness, - declarations, - } -} - /// Inline group fields and remove group declarations. -fn inline_groups(file: &parser_ast::File) -> Result<parser_ast::File, Diagnostics> { +fn inline_groups(file: &File) -> Result<File, Diagnostics> { fn inline_fields<'a>( - fields: impl Iterator<Item = &'a parser_ast::Field>, - groups: &HashMap<String, &parser_ast::Decl>, + fields: impl Iterator<Item = &'a Field>, + groups: &HashMap<String, &Decl>, constraints: &HashMap<String, Constraint>, - ) -> Vec<parser_ast::Field> { + ) -> Vec<Field> { fields .flat_map(|field| match &field.desc { FieldDesc::Group { group_id, constraints: group_constraints } => { @@ -1700,18 +1637,18 @@ fn inline_groups(file: &parser_ast::File) -> Result<parser_ast::File, Diagnostic inline_fields(groups.get(group_id).unwrap().fields(), groups, &constraints) } FieldDesc::Scalar { id, width } if constraints.contains_key(id) => { - vec![parser_ast::Field { + vec![Field { desc: FieldDesc::FixedScalar { width: *width, value: constraints.get(id).unwrap().value.unwrap(), }, loc: field.loc, - annot: field.annot, + key: field.key, cond: field.cond.clone(), }] } FieldDesc::Typedef { id, type_id, .. } if constraints.contains_key(id) => { - vec![parser_ast::Field { + vec![Field { desc: FieldDesc::FixedEnum { enum_id: type_id.clone(), tag_id: constraints @@ -1720,7 +1657,7 @@ fn inline_groups(file: &parser_ast::File) -> Result<parser_ast::File, Diagnostic .unwrap(), }, loc: field.loc, - annot: field.annot, + key: field.key, cond: field.cond.clone(), }] } @@ -1740,7 +1677,7 @@ fn inline_groups(file: &parser_ast::File) -> Result<parser_ast::File, Diagnostic .declarations .iter() .filter_map(|decl| match &decl.desc { - DeclDesc::Packet { fields, id, parent_id, constraints } => Some(parser_ast::Decl { + DeclDesc::Packet { fields, id, parent_id, constraints } => Some(Decl { desc: DeclDesc::Packet { fields: inline_fields(fields.iter(), &groups, &HashMap::new()), id: id.clone(), @@ -1748,9 +1685,9 @@ fn inline_groups(file: &parser_ast::File) -> Result<parser_ast::File, Diagnostic constraints: constraints.clone(), }, loc: decl.loc, - annot: decl.annot, + key: decl.key, }), - DeclDesc::Struct { fields, id, parent_id, constraints } => Some(parser_ast::Decl { + DeclDesc::Struct { fields, id, parent_id, constraints } => Some(Decl { desc: DeclDesc::Struct { fields: inline_fields(fields.iter(), &groups, &HashMap::new()), id: id.clone(), @@ -1758,7 +1695,7 @@ fn inline_groups(file: &parser_ast::File) -> Result<parser_ast::File, Diagnostic constraints: constraints.clone(), }, loc: decl.loc, - annot: decl.annot, + key: decl.key, }), DeclDesc::Group { .. } => None, _ => Some(decl.clone()), @@ -1767,17 +1704,18 @@ fn inline_groups(file: &parser_ast::File) -> Result<parser_ast::File, Diagnostic Ok(File { declarations, - version: file.version.clone(), file: file.file, comments: file.comments.clone(), endianness: file.endianness, + // Keys are reused for inlined fields. + max_key: file.max_key, }) } /// Replace Scalar fields used as condition for optional fields by the more /// specific Flag construct. -fn desugar_flags(file: &mut parser_ast::File) { +fn desugar_flags(file: &mut File) { for decl in &mut file.declarations { match &mut decl.desc { DeclDesc::Packet { fields, .. } @@ -1813,7 +1751,7 @@ fn desugar_flags(file: &mut parser_ast::File) { /// Analyzer entry point, produces a new AST with annotations resulting /// from the analysis. -pub fn analyze(file: &parser_ast::File) -> Result<ast::File, Diagnostics> { +pub fn analyze(file: &File) -> Result<File, Diagnostics> { let scope = Scope::new(file)?; check_decl_identifiers(file, &scope)?; check_field_identifiers(file)?; @@ -1830,13 +1768,13 @@ pub fn analyze(file: &parser_ast::File) -> Result<ast::File, Diagnostics> { desugar_flags(&mut file); let scope = Scope::new(&file)?; check_decl_constraints(&file, &scope)?; - Ok(compute_field_sizes(&file)) + Ok(file) } #[cfg(test)] mod test { use crate::analyzer; - use crate::ast::*; + use crate::ast; use crate::parser::parse_inline; use codespan_reporting::term::termcolor; @@ -1844,7 +1782,7 @@ mod test { macro_rules! raises { ($code:ident, $text:literal) => {{ - let mut db = SourceDatabase::new(); + let mut db = ast::SourceDatabase::new(); let file = parse_inline(&mut db, "stdin", $text.to_owned()).expect("parsing failure"); let result = analyzer::analyze(&file); assert!(matches!(result, Err(_))); @@ -1859,7 +1797,7 @@ mod test { macro_rules! valid { ($text:literal) => {{ - let mut db = SourceDatabase::new(); + let mut db = ast::SourceDatabase::new(); let file = parse_inline(&mut db, "stdin", $text.to_owned()).expect("parsing failure"); assert!(analyzer::analyze(&file).is_ok()); }}; @@ -3112,7 +3050,7 @@ mod test { ); } - use analyzer::ast::Size; + use analyzer::Size; use Size::*; #[derive(Debug, PartialEq, Eq)] @@ -3123,15 +3061,16 @@ mod test { } fn annotations(text: &str) -> Vec<Annotations> { - let mut db = SourceDatabase::new(); + let mut db = ast::SourceDatabase::new(); let file = parse_inline(&mut db, "stdin", text.to_owned()).expect("parsing failure"); let file = analyzer::analyze(&file).expect("analyzer failure"); + let schema = analyzer::Schema::new(&file); file.declarations .iter() .map(|decl| Annotations { - size: decl.annot.size, - payload_size: decl.annot.payload_size, - fields: decl.fields().map(|field| field.annot.size).collect(), + size: schema.decl_size(decl.key), + payload_size: schema.payload_size(decl.key), + fields: decl.fields().map(|field| schema.field_size(field.key)).collect(), }) .collect() } @@ -3626,8 +3565,8 @@ mod test { ); } - fn desugar(text: &str) -> analyzer::ast::File { - let mut db = SourceDatabase::new(); + fn desugar(text: &str) -> analyzer::File { + let mut db = ast::SourceDatabase::new(); let file = parse_inline(&mut db, "stdin", text.to_owned()).expect("parsing failure"); analyzer::analyze(&file).expect("analyzer failure") } @@ -43,11 +43,6 @@ pub struct SourceRange { pub end: SourceLocation, } -pub trait Annotation: fmt::Debug + Serialize { - type FieldAnnotation: Default + fmt::Debug + Clone; - type DeclAnnotation: Default + fmt::Debug + Clone; -} - #[derive(Debug, Serialize, Clone)] #[serde(tag = "kind", rename = "comment")] pub struct Comment { @@ -110,6 +105,9 @@ pub struct Constraint { pub tag_id: Option<String>, } +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct FieldKey(pub usize); + #[derive(Debug, Serialize, Clone, PartialEq, Eq)] #[serde(tag = "kind")] pub enum FieldDesc { @@ -154,10 +152,12 @@ pub enum FieldDesc { } #[derive(Debug, Serialize, Clone)] -pub struct Field<A: Annotation> { +pub struct Field { pub loc: SourceRange, + /// Unique identifier used to refer to the AST node in + /// compilation environments. #[serde(skip_serializing)] - pub annot: A::FieldAnnotation, + pub key: FieldKey, #[serde(flatten)] pub desc: FieldDesc, pub cond: Option<Constraint>, @@ -170,9 +170,12 @@ pub struct TestCase { pub input: String, } +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct DeclKey(pub usize); + #[derive(Debug, Serialize, Clone, PartialEq, Eq)] #[serde(tag = "kind")] -pub enum DeclDesc<A: Annotation> { +pub enum DeclDesc { #[serde(rename = "checksum_declaration")] Checksum { id: String, function: String, width: usize }, #[serde(rename = "custom_field_declaration")] @@ -183,38 +186,42 @@ pub enum DeclDesc<A: Annotation> { Packet { id: String, constraints: Vec<Constraint>, - fields: Vec<Field<A>>, + fields: Vec<Field>, parent_id: Option<String>, }, #[serde(rename = "struct_declaration")] Struct { id: String, constraints: Vec<Constraint>, - fields: Vec<Field<A>>, + fields: Vec<Field>, parent_id: Option<String>, }, #[serde(rename = "group_declaration")] - Group { id: String, fields: Vec<Field<A>> }, + Group { id: String, fields: Vec<Field> }, #[serde(rename = "test_declaration")] Test { type_id: String, test_cases: Vec<TestCase> }, } #[derive(Debug, Serialize, Clone)] -pub struct Decl<A: Annotation> { +pub struct Decl { pub loc: SourceRange, + /// Unique identifier used to refer to the AST node in + /// compilation environments. #[serde(skip_serializing)] - pub annot: A::DeclAnnotation, + pub key: DeclKey, #[serde(flatten)] - pub desc: DeclDesc<A>, + pub desc: DeclDesc, } #[derive(Debug, Serialize, Clone)] -pub struct File<A: Annotation> { +pub struct File { pub version: String, pub file: FileId, pub comments: Vec<Comment>, pub endianness: Endianness, - pub declarations: Vec<Decl<A>>, + pub declarations: Vec<Decl>, + #[serde(skip_serializing)] + pub max_key: usize, } impl SourceLocation { @@ -350,8 +357,8 @@ impl PartialEq for TestCase { } } -impl<A: Annotation + PartialEq> Eq for File<A> {} -impl<A: Annotation + PartialEq> PartialEq for File<A> { +impl Eq for File {} +impl PartialEq for File { fn eq(&self, other: &Self) -> bool { // Implement structural equality, leave out comments and PDL // version information. @@ -359,8 +366,8 @@ impl<A: Annotation + PartialEq> PartialEq for File<A> { } } -impl<A: Annotation> File<A> { - pub fn new(file: FileId) -> File<A> { +impl File { + pub fn new(file: FileId) -> File { File { version: "1,0".to_owned(), comments: vec![], @@ -372,71 +379,27 @@ impl<A: Annotation> File<A> { }, declarations: vec![], file, + max_key: 0, } } /// Iterate over the children of the selected declaration. /// /!\ This method is unsafe to use if the file contains cyclic /// declarations, use with caution. - pub fn iter_children<'d>(&'d self, decl: &'d Decl<A>) -> impl Iterator<Item = &'d Decl<A>> { + pub fn iter_children<'d>(&'d self, decl: &'d Decl) -> impl Iterator<Item = &'d Decl> { self.declarations.iter().filter(|other_decl| other_decl.parent_id() == decl.id()) } } -impl<A: Annotation + PartialEq> Eq for Decl<A> {} -impl<A: Annotation + PartialEq> PartialEq for Decl<A> { +impl Eq for Decl {} +impl PartialEq for Decl { fn eq(&self, other: &Self) -> bool { - // Implement structural equality, leave out loc and annot. + // Implement structural equality, leave out loc and key. self.desc == other.desc } } -impl<A: Annotation> Decl<A> { - pub fn new(loc: SourceRange, desc: DeclDesc<A>) -> Decl<A> { - Decl { loc, annot: Default::default(), desc } - } - - pub fn annotate<F, B: Annotation>( - &self, - annot: B::DeclAnnotation, - annotate_fields: F, - ) -> Decl<B> - where - F: FnOnce(&[Field<A>]) -> Vec<Field<B>>, - { - let desc = match &self.desc { - DeclDesc::Checksum { id, function, width } => { - DeclDesc::Checksum { id: id.clone(), function: function.clone(), width: *width } - } - DeclDesc::CustomField { id, width, function } => { - DeclDesc::CustomField { id: id.clone(), width: *width, function: function.clone() } - } - DeclDesc::Enum { id, tags, width } => { - DeclDesc::Enum { id: id.clone(), tags: tags.clone(), width: *width } - } - - DeclDesc::Test { type_id, test_cases } => { - DeclDesc::Test { type_id: type_id.clone(), test_cases: test_cases.clone() } - } - DeclDesc::Packet { id, constraints, parent_id, fields } => DeclDesc::Packet { - id: id.clone(), - constraints: constraints.clone(), - parent_id: parent_id.clone(), - fields: annotate_fields(fields), - }, - DeclDesc::Struct { id, constraints, parent_id, fields } => DeclDesc::Struct { - id: id.clone(), - constraints: constraints.clone(), - parent_id: parent_id.clone(), - fields: annotate_fields(fields), - }, - DeclDesc::Group { id, fields } => { - DeclDesc::Group { id: id.clone(), fields: annotate_fields(fields) } - } - }; - Decl { loc: self.loc, desc, annot } - } - +impl Decl { pub fn id(&self) -> Option<&str> { match &self.desc { DeclDesc::Test { .. } => None, @@ -467,7 +430,7 @@ impl<A: Annotation> Decl<A> { } } - pub fn fields(&self) -> std::slice::Iter<'_, Field<A>> { + pub fn fields(&self) -> std::slice::Iter<'_, Field> { match &self.desc { DeclDesc::Packet { fields, .. } | DeclDesc::Struct { fields, .. } @@ -478,14 +441,14 @@ 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>> { + pub fn payload(&self) -> Option<&Field> { 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>> { + pub fn payload_size(&self) -> Option<&Field> { self.fields().find(|field| match &field.desc { FieldDesc::Size { field_id, .. } => field_id == "_payload_" || field_id == "_body_", _ => false, @@ -494,7 +457,7 @@ impl<A: Annotation> Decl<A> { /// 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>> { + pub fn array_size(&self, id: &str) -> Option<&Field> { self.fields().find(|field| match &field.desc { FieldDesc::Size { field_id, .. } | FieldDesc::Count { field_id, .. } => field_id == id, _ => false, @@ -514,19 +477,15 @@ impl<A: Annotation> Decl<A> { } } -impl<A: Annotation> Eq for Field<A> {} -impl<A: Annotation> PartialEq for Field<A> { +impl Eq for Field {} +impl PartialEq for Field { fn eq(&self, other: &Self) -> bool { // Implement structural equality, leave out loc and annot. self.desc == other.desc } } -impl<A: Annotation> Field<A> { - pub fn annotate<B: Annotation>(&self, annot: B::FieldAnnotation) -> Field<B> { - Field { loc: self.loc, annot, cond: self.cond.clone(), desc: self.desc.clone() } - } - +impl Field { pub fn id(&self) -> Option<&str> { match &self.desc { FieldDesc::Checksum { .. } diff --git a/src/backends.rs b/src/backends.rs index a80f1f9..79058fa 100644 --- a/src/backends.rs +++ b/src/backends.rs @@ -17,4 +17,5 @@ pub mod intermediate; pub mod json; pub mod rust; +pub mod rust_legacy; pub mod rust_no_allocation; diff --git a/src/backends/intermediate.rs b/src/backends/intermediate.rs index 4c92ae0..cdae0f1 100644 --- a/src/backends/intermediate.rs +++ b/src/backends/intermediate.rs @@ -15,7 +15,6 @@ use std::collections::{btree_map::Entry, BTreeMap, HashMap}; use crate::ast; -use crate::parser; pub struct Schema<'a> { pub packets_and_structs: HashMap<&'a str, PacketOrStruct<'a>>, @@ -98,7 +97,7 @@ pub enum ComputedOffset<'a> { Alias(ComputedOffsetId<'a>), } -pub fn generate(file: &parser::ast::File) -> Result<Schema, String> { +pub fn generate(file: &ast::File) -> Result<Schema, String> { let mut schema = Schema { packets_and_structs: HashMap::new(), enums: HashMap::new() }; match file.endianness.value { ast::EndiannessValue::LittleEndian => {} @@ -112,7 +111,7 @@ pub fn generate(file: &parser::ast::File) -> Result<Schema, String> { Ok(schema) } -fn process_decl<'a>(schema: &mut Schema<'a>, decl: &'a parser::ast::Decl) { +fn process_decl<'a>(schema: &mut Schema<'a>, decl: &'a ast::Decl) { match &decl.desc { ast::DeclDesc::Enum { id, tags, width, .. } => process_enum(schema, id, tags, *width), ast::DeclDesc::Packet { id, fields, .. } | ast::DeclDesc::Struct { id, fields, .. } => { @@ -135,18 +134,11 @@ fn process_enum<'a>(schema: &mut Schema<'a>, id: &'a str, tags: &'a [ast::Tag], ); } -fn process_packet_or_struct<'a>( - schema: &mut Schema<'a>, - id: &'a str, - fields: &'a [parser::ast::Field], -) { +fn process_packet_or_struct<'a>(schema: &mut Schema<'a>, id: &'a str, fields: &'a [ast::Field]) { schema.packets_and_structs.insert(id, compute_getters(schema, fields)); } -fn compute_getters<'a>( - schema: &Schema<'a>, - fields: &'a [parser::ast::Field], -) -> PacketOrStruct<'a> { +fn compute_getters<'a>(schema: &Schema<'a>, fields: &'a [ast::Field]) -> PacketOrStruct<'a> { let mut prev_pos_id = None; let mut curr_pos_id = ComputedOffsetId::HeaderStart; let mut computed_values = BTreeMap::new(); diff --git a/src/backends/json.rs b/src/backends/json.rs index 526b29e..7bd6e4f 100644 --- a/src/backends/json.rs +++ b/src/backends/json.rs @@ -14,10 +14,10 @@ //! Json compiler backend. -use crate::parser; +use crate::ast; /// Turn the AST into a JSON representation. -pub fn generate(file: &parser::ast::File) -> Result<String, String> { +pub fn generate(file: &ast::File) -> Result<String, String> { serde_json::to_string_pretty(&file) .map_err(|err| format!("could not JSON serialize grammar: {err}")) } diff --git a/src/backends/rust/mod.rs b/src/backends/rust/mod.rs new file mode 100644 index 0000000..0e57eb8 --- /dev/null +++ b/src/backends/rust/mod.rs @@ -0,0 +1,1723 @@ +// 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. + +//! Rust compiler backend. + +use crate::{analyzer, ast}; +use quote::{format_ident, quote}; +use std::collections::BTreeSet; +use std::collections::HashMap; +use std::path::Path; +use syn::LitInt; + +mod parser; +mod preamble; +mod serializer; +pub mod test; +mod types; + +pub use heck::ToUpperCamelCase; +use parser::FieldParser; + +pub trait ToIdent { + /// Generate a sanitized rust identifier. + /// Rust specific keywords are renamed for validity. + fn to_ident(self) -> proc_macro2::Ident; +} + +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), + } + } +} + +/// Generate a bit-mask which masks out `n` least significant bits. +/// +/// Literal integers in Rust default to the `i32` type. For this +/// reason, if `n` is larger than 31, a suffix is added to the +/// `LitInt` returned. This should either be `u64` or `usize` +/// depending on where the result is used. +pub fn mask_bits(n: usize, suffix: &str) -> syn::LitInt { + let suffix = if n > 31 { format!("_{suffix}") } else { String::new() }; + // Format the hex digits as 0x1111_2222_3333_usize. + let hex_digits = format!("{:x}", (1u64 << n) - 1) + .as_bytes() + .rchunks(4) + .rev() + .map(|chunk| std::str::from_utf8(chunk).unwrap()) + .collect::<Vec<&str>>() + .join("_"); + syn::parse_str::<syn::LitInt>(&format!("0x{hex_digits}{suffix}")).unwrap() +} + +/// Return the list of fields that will appear in the generated +/// rust structs (<Packet> and <Packet>Builder). +/// - must be a named field +/// - must not be a flag +/// - must not appear in the packet constraints. +/// The fields are presented in declaration order, with ancestor +/// fields declared first. +/// The payload field _ if declared _ is handled separately. +fn packet_data_fields<'a>( + scope: &'a analyzer::Scope<'a>, + decl: &'a ast::Decl, +) -> Vec<&'a ast::Field> { + let all_constraints = HashMap::<String, _>::from_iter( + scope.iter_constraints(decl).map(|c| (c.id.to_string(), c)), + ); + + scope + .iter_fields(decl) + .filter(|f| f.id().is_some()) + .filter(|f| !matches!(&f.desc, ast::FieldDesc::Flag { .. })) + .filter(|f| !all_constraints.contains_key(f.id().unwrap())) + .collect::<Vec<_>>() +} + +/// Return the list of fields that have a constant value. +/// The fields are presented in declaration order, with ancestor +/// fields declared first. +fn packet_constant_fields<'a>( + scope: &'a analyzer::Scope<'a>, + decl: &'a ast::Decl, +) -> Vec<&'a ast::Field> { + let all_constraints = HashMap::<String, _>::from_iter( + scope.iter_constraints(decl).map(|c| (c.id.to_string(), c)), + ); + + scope + .iter_fields(decl) + .filter(|f| f.id().is_some()) + .filter(|f| all_constraints.contains_key(f.id().unwrap())) + .collect::<Vec<_>>() +} + +fn constraint_value( + fields: &[&'_ ast::Field], + constraint: &ast::Constraint, +) -> proc_macro2::TokenStream { + match constraint { + ast::Constraint { value: Some(value), .. } => { + let value = proc_macro2::Literal::usize_unsuffixed(*value); + quote!(#value) + } + // TODO(mgeisler): include type_id in `ast::Constraint` and + // drop the packet_scope argument. + ast::Constraint { tag_id: Some(tag_id), .. } => { + let tag_id = format_ident!("{}", tag_id.to_upper_camel_case()); + let type_id = fields + .iter() + .filter_map(|f| match &f.desc { + ast::FieldDesc::Typedef { id, type_id } if id == &constraint.id => { + Some(type_id.to_ident()) + } + _ => None, + }) + .next() + .unwrap(); + quote!(#type_id::#tag_id) + } + _ => unreachable!("Invalid constraint: {constraint:?}"), + } +} + +fn constraint_value_str(fields: &[&'_ ast::Field], constraint: &ast::Constraint) -> String { + match constraint { + ast::Constraint { value: Some(value), .. } => { + format!("{}", value) + } + ast::Constraint { tag_id: Some(tag_id), .. } => { + let tag_id = format_ident!("{}", tag_id.to_upper_camel_case()); + let type_id = fields + .iter() + .filter_map(|f| match &f.desc { + ast::FieldDesc::Typedef { id, type_id } if id == &constraint.id => { + Some(type_id.to_ident()) + } + _ => None, + }) + .next() + .unwrap(); + format!("{}::{}", type_id, tag_id) + } + _ => unreachable!("Invalid constraint: {constraint:?}"), + } +} + +fn implements_copy(scope: &analyzer::Scope<'_>, field: &ast::Field) -> bool { + match &field.desc { + ast::FieldDesc::Scalar { .. } => true, + ast::FieldDesc::Typedef { type_id, .. } => match &scope.typedef[type_id].desc { + ast::DeclDesc::Enum { .. } | ast::DeclDesc::CustomField { .. } => true, + ast::DeclDesc::Struct { .. } => false, + desc => unreachable!("unexpected declaration: {desc:?}"), + }, + ast::FieldDesc::Array { .. } => false, + _ => todo!(), + } +} + +/// Generate code for a root packet declaration. +/// +/// # Arguments +/// * `endianness` - File endianness +/// * `id` - Packet identifier. +fn generate_root_packet_decl( + scope: &analyzer::Scope<'_>, + schema: &analyzer::Schema, + endianness: ast::EndiannessValue, + id: &str, +) -> proc_macro2::TokenStream { + let decl = scope.typedef[id]; + let name = id.to_ident(); + let child_name = format_ident!("{id}Child"); + + // Return the list of fields that will appear in the generated + // rust structs (<Packet> and <Packet>Builder). + // The payload field _ if declared _ is handled separately. + let data_fields = packet_data_fields(scope, decl); + let data_field_ids = data_fields.iter().map(|f| f.id().unwrap().to_ident()).collect::<Vec<_>>(); + let data_field_types = data_fields.iter().map(|f| types::rust_type(f)).collect::<Vec<_>>(); + let data_field_borrows = data_fields + .iter() + .map(|f| { + if implements_copy(scope, f) { + quote! {} + } else { + quote! { & } + } + }) + .collect::<Vec<_>>(); + let payload_field = decl.payload().map(|_| quote! { pub payload: Vec<u8>, }); + let payload_accessor = + decl.payload().map(|_| quote! { pub fn payload(&self) -> &[u8] { &self.payload } }); + + let parser_span = format_ident!("buf"); + let mut field_parser = FieldParser::new(scope, schema, endianness, id, &parser_span); + for field in decl.fields() { + field_parser.add(field); + } + + // For the implementation of decode_partial, sort the data field identifiers + // between parsed fields (extracted from the payload), and copied fields + // (copied from the parent). + let mut parsed_field_ids = vec![]; + if decl.payload().is_some() { + parsed_field_ids.push(format_ident!("payload")); + } + for f in &data_fields { + let id = f.id().unwrap().to_ident(); + parsed_field_ids.push(id); + } + + let (encode_fields, encoded_len) = + serializer::encode(scope, schema, endianness, "buf".to_ident(), decl); + + let encode = quote! { + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + #encode_fields + Ok(()) + } + }; + + // Compute the encoded length of the packet. + let encoded_len = quote! { + fn encoded_len(&self) -> usize { + #encoded_len + } + }; + + // The implementation of decode for root packets contains the full + // parser implementation. + let decode = quote! { + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + #field_parser + Ok((Self { #( #parsed_field_ids, )* }, buf)) + } + }; + + // Provide the implementation of the enum listing child declarations of the + // current declaration. This enum is only provided for declarations that + // have child packets. + let children_decl = scope.iter_children(decl).collect::<Vec<_>>(); + let child_struct = (!children_decl.is_empty()).then(|| { + let children_ids = children_decl.iter().map(|decl| decl.id().unwrap().to_ident()); + quote! { + #[derive(Debug, Clone, PartialEq, Eq)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub enum #child_name { + #( #children_ids(#children_ids), )* + None, + } + } + }); + + // Provide the implementation of the specialization function. + // The specialization function is only provided for declarations that have + // child packets. + let specialize = (!children_decl.is_empty()).then(|| { + // Gather fields that are constrained in immediate child declarations. + // Keep the fields sorted by name. + let constraint_fields = children_decl + .iter() + .flat_map(|decl| decl.constraints().map(|c| c.id.to_owned())) + .collect::<BTreeSet<_>>(); + let constraint_ids = constraint_fields.iter().map(|id| id.to_ident()); + let children_ids = children_decl.iter().map(|decl| decl.id().unwrap().to_ident()); + + // Build the case values and case branches. + // The case are ordered by child declaration order. + // TODO(henrichataing) ambiguities should be resolved by trying each + // case until one is successfully parsed. + let case_values = children_decl.iter().map(|child_decl| { + let constraint_values = constraint_fields.iter().map(|id| { + let constraint = child_decl.constraints().find(|c| &c.id == id); + match constraint { + Some(constraint) => constraint_value(&data_fields, constraint), + None => quote! { _ }, + } + }); + quote! { (#( #constraint_values, )*) } + }); + + // TODO(henrichataing) the default case is necessary only if the match + // is non-exhaustive. + let default_case = quote! { _ => #child_name::None, }; + + quote! { + pub fn specialize(&self) -> Result<#child_name, DecodeError> { + Ok( + match (#( self.#constraint_ids, )*) { + #( #case_values => + #child_name::#children_ids(self.try_into()?), )* + #default_case + } + ) + } + } + }); + + quote! { + #[derive(Debug, Clone, PartialEq, Eq)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct #name { + #( pub #data_field_ids: #data_field_types, )* + #payload_field + } + + #child_struct + + impl #name { + #specialize + #payload_accessor + + #( + pub fn #data_field_ids(&self) -> #data_field_borrows #data_field_types { + #data_field_borrows self.#data_field_ids + } + )* + } + + impl Packet for #name { + #encoded_len + #encode + #decode + } + } +} + +/// Generate code for a derived packet declaration +/// +/// # Arguments +/// * `endianness` - File endianness +/// * `id` - Packet identifier. +fn generate_derived_packet_decl( + scope: &analyzer::Scope<'_>, + schema: &analyzer::Schema, + endianness: ast::EndiannessValue, + id: &str, +) -> proc_macro2::TokenStream { + let decl = scope.typedef[id]; + let name = id.to_ident(); + let parent_decl = scope.get_parent(decl).unwrap(); + let parent_name = parent_decl.id().unwrap().to_ident(); + let child_name = format_ident!("{id}Child"); + + // Extract all constraint values from the parent declarations. + let all_constraints = HashMap::<String, _>::from_iter( + scope.iter_constraints(decl).map(|c| (c.id.to_string(), c)), + ); + + let all_fields = scope.iter_fields(decl).collect::<Vec<_>>(); + + // Return the list of fields that will appear in the generated + // rust structs (<Packet> and <Packet>Builder). + // The payload field _ if declared _ is handled separately. + let data_fields = packet_data_fields(scope, decl); + let data_field_ids = data_fields.iter().map(|f| f.id().unwrap().to_ident()).collect::<Vec<_>>(); + let data_field_types = data_fields.iter().map(|f| types::rust_type(f)).collect::<Vec<_>>(); + let data_field_borrows = data_fields + .iter() + .map(|f| { + if implements_copy(scope, f) { + quote! {} + } else { + quote! { & } + } + }) + .collect::<Vec<_>>(); + let payload_field = decl.payload().map(|_| quote! { pub payload: Vec<u8>, }); + let payload_accessor = + decl.payload().map(|_| quote! { pub fn payload(&self) -> &[u8] { &self.payload } }); + + let parent_data_fields = packet_data_fields(scope, parent_decl); + + // Return the list of fields that have a constant value. + let constant_fields = packet_constant_fields(scope, decl); + let constant_field_ids = + constant_fields.iter().map(|f| f.id().unwrap().to_ident()).collect::<Vec<_>>(); + let constant_field_types = + constant_fields.iter().map(|f| types::rust_type(f)).collect::<Vec<_>>(); + let constant_field_values = constant_fields.iter().map(|f| { + let c = all_constraints.get(f.id().unwrap()).unwrap(); + constraint_value(&all_fields, c) + }); + + // Generate field parsing and serialization. + let parser_span = format_ident!("buf"); + let mut field_parser = FieldParser::new(scope, schema, endianness, id, &parser_span); + for field in decl.fields() { + field_parser.add(field); + } + + // For the implementation of decode_partial, sort the data field identifiers + // between parsed fields (extracted from the payload), and copied fields + // (copied from the parent). + let mut parsed_field_ids = vec![]; + let mut copied_field_ids = vec![]; + let mut cloned_field_ids = vec![]; + if decl.payload().is_some() { + parsed_field_ids.push(format_ident!("payload")); + } + for f in &data_fields { + let id = f.id().unwrap().to_ident(); + if decl.fields().any(|ff| f.id() == ff.id()) { + parsed_field_ids.push(id); + } else if implements_copy(scope, f) { + copied_field_ids.push(id); + } else { + cloned_field_ids.push(id); + } + } + + let (partial_field_serializer, field_serializer, encoded_len) = + serializer::encode_partial(scope, schema, endianness, "buf".to_ident(), decl); + + let encode_partial = quote! { + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + #partial_field_serializer + Ok(()) + } + }; + + let encode = quote! { + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + #field_serializer + Ok(()) + } + }; + + // Compute the encoded length of the packet. + let encoded_len = quote! { + fn encoded_len(&self) -> usize { + #encoded_len + } + }; + + // Constraint checks are only run for constraints added to this declaration + // and not parent constraints which are expected to have been validated + // earlier. + let constraint_checks = decl.constraints().map(|c| { + let field_id = c.id.to_ident(); + let field_name = &c.id; + let packet_name = id; + let value = constraint_value(&parent_data_fields, c); + let value_str = constraint_value_str(&parent_data_fields, c); + quote! { + if parent.#field_id() != #value { + return Err(DecodeError::InvalidFieldValue { + packet: #packet_name, + field: #field_name, + expected: #value_str, + actual: format!("{:?}", parent.#field_id()), + }) + } + } + }); + + let decode_partial = if parent_decl.payload().is_some() { + // Generate an implementation of decode_partial that will decode + // data fields present in the parent payload. + // TODO(henrichataing) add constraint validation to decode_partial, + // return DecodeError::InvalidConstraint. + quote! { + fn decode_partial(parent: &#parent_name) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + #( #constraint_checks )* + #field_parser + if buf.is_empty() { + Ok(Self { + #( #parsed_field_ids, )* + #( #copied_field_ids: parent.#copied_field_ids, )* + #( #cloned_field_ids: parent.#cloned_field_ids.clone(), )* + }) + } else { + Err(DecodeError::TrailingBytes) + } + } + } + } else { + // Generate an implementation of decode_partial that will only copy + // data fields present in the parent. + // TODO(henrichataing) add constraint validation to decode_partial, + // return DecodeError::InvalidConstraint. + quote! { + fn decode_partial(parent: &#parent_name) -> Result<Self, DecodeError> { + #( #constraint_checks )* + Ok(Self { + #( #copied_field_ids: parent.#copied_field_ids, )* + }) + } + } + }; + + let decode = + // The implementation of decode for derived packets relies on + // the parent packet parser. + quote! { + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = #parent_name::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } + }; + + // Provide the implementation of conversion helpers from + // the current packet to its parent packets. The implementation + // is explicit for the immediate parent, and derived using other + // Into<> implementations for the ancestors. + let into_parent = { + let parent_data_field_ids = parent_data_fields.iter().map(|f| f.id().unwrap().to_ident()); + let parent_data_field_values = parent_data_fields.iter().map(|f| { + let id = f.id().unwrap().to_ident(); + match all_constraints.get(f.id().unwrap()) { + Some(c) => constraint_value(&parent_data_fields, c), + None => quote! { packet.#id }, + } + }); + if parent_decl.payload().is_some() { + quote! { + impl TryFrom<&#name> for #parent_name { + type Error = EncodeError; + fn try_from(packet: &#name) -> Result<#parent_name, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(#parent_name { + #( #parent_data_field_ids: #parent_data_field_values, )* + payload, + }) + } + } + + impl TryFrom<#name> for #parent_name { + type Error = EncodeError; + fn try_from(packet: #name) -> Result<#parent_name, Self::Error> { + (&packet).try_into() + } + } + } + } else { + quote! { + impl From<&#name> for #parent_name { + fn from(packet: &#name) -> #parent_name { + #parent_name { + #( #parent_data_field_ids: #parent_data_field_values, )* + } + } + } + + impl From<#name> for #parent_name { + fn from(packet: #name) -> #parent_name { + (&packet).into() + } + } + } + } + }; + + let into_ancestors = scope.iter_parents(parent_decl).map(|ancestor_decl| { + let ancestor_name = ancestor_decl.id().unwrap().to_ident(); + quote! { + impl TryFrom<&#name> for #ancestor_name { + type Error = EncodeError; + fn try_from(packet: &#name) -> Result<#ancestor_name, Self::Error> { + (&#parent_name::try_from(packet)?).try_into() + } + } + + impl TryFrom<#name> for #ancestor_name { + type Error = EncodeError; + fn try_from(packet: #name) -> Result<#ancestor_name, Self::Error> { + (&packet).try_into() + } + } + } + }); + + // Provide the implementation of conversion helper from + // the parent packet. This function is actually the parse + // implementation. This helper is provided only if the packet has a + // parent declaration. + let try_from_parent = quote! { + impl TryFrom<&#parent_name> for #name { + type Error = DecodeError; + fn try_from(parent: &#parent_name) -> Result<#name, Self::Error> { + #name::decode_partial(&parent) + } + } + + impl TryFrom<#parent_name> for #name { + type Error = DecodeError; + fn try_from(parent: #parent_name) -> Result<#name, Self::Error> { + (&parent).try_into() + } + } + }; + + // Provide the implementation of the enum listing child declarations of the + // current declaration. This enum is only provided for declarations that + // have child packets. + let children_decl = scope.iter_children(decl).collect::<Vec<_>>(); + let child_struct = (!children_decl.is_empty()).then(|| { + let children_ids = children_decl.iter().map(|decl| decl.id().unwrap().to_ident()); + quote! { + #[derive(Debug, Clone, PartialEq, Eq)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub enum #child_name { + #( #children_ids(#children_ids), )* + None, + } + } + }); + + // Provide the implementation of the specialization function. + // The specialization function is only provided for declarations that have + // child packets. + let specialize = (!children_decl.is_empty()).then(|| { + // Gather fields that are constrained in immediate child declarations. + // Keep the fields sorted by name. + let constraint_fields = children_decl + .iter() + .flat_map(|decl| decl.constraints().map(|c| c.id.to_owned())) + .collect::<BTreeSet<_>>(); + let constraint_ids = constraint_fields.iter().map(|id| id.to_ident()); + let children_ids = children_decl.iter().map(|decl| decl.id().unwrap().to_ident()); + + // Build the case values and case branches. + // The case are ordered by child declaration order. + // TODO(henrichataing) ambiguities should be resolved by trying each + // case until one is successfully parsed. + let case_values = children_decl.iter().map(|child_decl| { + let constraint_values = constraint_fields.iter().map(|id| { + let constraint = child_decl.constraints().find(|c| &c.id == id); + match constraint { + Some(constraint) => constraint_value(&data_fields, constraint), + None => quote! { _ }, + } + }); + quote! { (#( #constraint_values, )*) } + }); + + // TODO(henrichataing) the default case is necessary only if the match + // is non-exhaustive. + let default_case = quote! { _ => #child_name::None, }; + + quote! { + pub fn specialize(&self) -> Result<#child_name, DecodeError> { + Ok( + match (#( self.#constraint_ids, )*) { + #( #case_values => + #child_name::#children_ids(self.try_into()?), )* + #default_case + } + ) + } + } + }); + + quote! { + #[derive(Debug, Clone, PartialEq, Eq)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + pub struct #name { + #( pub #data_field_ids: #data_field_types, )* + #payload_field + } + + #try_from_parent + #into_parent + #( #into_ancestors )* + + #child_struct + + impl #name { + #specialize + #decode_partial + #encode_partial + #payload_accessor + + #( + pub fn #data_field_ids(&self) -> #data_field_borrows #data_field_types { + #data_field_borrows self.#data_field_ids + } + )* + + #( + pub fn #constant_field_ids(&self) -> #constant_field_types { + #constant_field_values + } + )* + } + + impl Packet for #name { + #encoded_len + #encode + #decode + } + } +} + +/// Generate an enum declaration. +/// +/// # Arguments +/// * `id` - Enum identifier. +/// * `tags` - List of enum tags. +/// * `width` - Width of the backing type of the enum, in bits. +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() + } + + // 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, + }) + .collect::<Vec<_>>(); + ranges.sort_unstable(); + ranges.first().unwrap().0 == 0 + && ranges.last().unwrap().1 == max + && ranges.windows(2).all(|window| { + if let [left, right] = window { + left.1 == right.0 - 1 + } else { + false + } + }) + } + + // 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(_))) + } + + // Return the maximum value for the scalar type. + fn scalar_max(width: usize) -> usize { + if width >= usize::BITS as usize { + usize::MAX + } else { + (1 << width) - 1 + } + } + + // Format an enum tag identifier to rust upper caml case. + fn format_tag_ident(id: &str) -> proc_macro2::TokenStream { + let id = format_ident!("{}", id.to_upper_camel_case()); + quote! { #id } + } + + // Format a constant value as hexadecimal constant. + fn format_value(value: usize) -> LitInt { + syn::parse_str::<syn::LitInt>(&format!("{:#x}", value)).unwrap() + } + + // Backing type for the enum. + 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(); + + // 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 repr_u64 = use_variant_values.then(|| quote! { #[repr(u64)] }); + let mut variants = vec![]; + for tag in tags.iter() { + match tag { + ast::Tag::Value(tag) if use_variant_values => { + let id = format_tag_ident(&tag.id); + let value = format_value(tag.value); + variants.push(quote! { #id = #value }) + } + ast::Tag::Value(tag) => variants.push(format_tag_ident(&tag.id)), + ast::Tag::Range(tag) => { + variants.extend(tag.tags.iter().map(|tag| format_tag_ident(&tag.id))); + let id = format_tag_ident(&tag.id); + variants.push(quote! { #id(Private<#backing_type>) }) + } + ast::Tag::Other(_) => (), + } + } + + // Generate the cases for parsing the enum value from an integer. + let mut from_cases = vec![]; + for tag in tags.iter() { + match tag { + ast::Tag::Value(tag) => { + let id = format_tag_ident(&tag.id); + let value = format_value(tag.value); + from_cases.push(quote! { #value => Ok(#name::#id) }) + } + ast::Tag::Range(tag) => { + from_cases.extend(tag.tags.iter().map(|tag| { + let id = format_tag_ident(&tag.id); + let value = format_value(tag.value); + quote! { #value => Ok(#name::#id) } + })); + let id = format_tag_ident(&tag.id); + let start = format_value(*tag.range.start()); + let end = format_value(*tag.range.end()); + from_cases.push(quote! { #start ..= #end => Ok(#name::#id(Private(value))) }) + } + ast::Tag::Other(_) => (), + } + } + + // Generate the cases for serializing the enum value to an integer. + let mut into_cases = vec![]; + for tag in tags.iter() { + match tag { + ast::Tag::Value(tag) => { + let id = format_tag_ident(&tag.id); + let value = format_value(tag.value); + into_cases.push(quote! { #name::#id => #value }) + } + ast::Tag::Range(tag) => { + into_cases.extend(tag.tags.iter().map(|tag| { + let id = format_tag_ident(&tag.id); + let value = format_value(tag.value); + quote! { #name::#id => #value } + })); + 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 }); + } + + // 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) { + from_cases.push(quote! { _ => Err(value) }); + } + + // Derive other Into<uN> and Into<iN> implementations from the explicit + // implementation, where the type is larger than the backing type. + let derived_signed_into_types = [8, 16, 32, 64] + .into_iter() + .filter(|w| *w > width) + .map(|w| syn::parse_str::<syn::Type>(&format!("i{}", w)).unwrap()); + let derived_unsigned_into_types = [8, 16, 32, 64] + .into_iter() + .filter(|w| *w >= width && *w != backing_type.width) + .map(|w| syn::parse_str::<syn::Type>(&format!("u{}", w)).unwrap()); + let derived_into_types = derived_signed_into_types.chain(derived_unsigned_into_types); + + quote! { + #repr_u64 + #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + #[cfg_attr(feature = "serde", serde(try_from = #backing_type_str, into = #backing_type_str))] + pub enum #name { + #(#variants,)* + } + + impl TryFrom<#backing_type> for #name { + type Error = #backing_type; + fn try_from(value: #backing_type) -> Result<Self, Self::Error> { + match value { + #(#from_cases,)* + } + } + } + + impl From<&#name> for #backing_type { + fn from(value: &#name) -> Self { + match value { + #(#into_cases,)* + } + } + } + + impl From<#name> for #backing_type { + fn from(value: #name) -> Self { + (&value).into() + } + } + + #(impl From<#name> for #derived_into_types { + fn from(value: #name) -> Self { + #backing_type::from(value) as Self + } + })* + } +} + +/// Generate the declaration for a custom field of static size. +/// +/// * `id` - Enum identifier. +/// * `width` - Width of the backing type of the enum, in bits. +fn generate_custom_field_decl( + endianness: ast::EndiannessValue, + id: &str, + width: usize, +) -> proc_macro2::TokenStream { + let name = id; + let id = id.to_ident(); + 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)); + let size = proc_macro2::Literal::usize_unsuffixed(width / 8); + + let read_value = types::get_uint(endianness, width, &format_ident!("buf")); + let read_value = if [8, 16, 32, 64].contains(&width) { + quote! { #read_value.into() } + } else { + // The value is masked when read, and the conversion must succeed. + quote! { (#read_value).try_into().unwrap() } + }; + + let write_value = types::put_uint( + endianness, + "e! { #backing_type::from(self) }, + width, + &format_ident!("buf"), + ); + + let common = quote! { + impl From<&#id> for #backing_type { + fn from(value: &#id) -> #backing_type { + value.0 + } + } + + impl From<#id> for #backing_type { + fn from(value: #id) -> #backing_type { + value.0 + } + } + + impl Packet for #id { + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.len() < #size { + return Err(DecodeError::InvalidLengthError { + obj: #name, + wanted: #size, + got: buf.len(), + }) + } + + Ok((#read_value, buf)) + } + + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + #write_value; + Ok(()) + } + + fn encoded_len(&self) -> usize { + #size + } + } + }; + + if backing_type.width == width { + quote! { + #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + #[cfg_attr(feature = "serde", serde(from = #backing_type_str, into = #backing_type_str))] + pub struct #id(#backing_type); + + #common + + impl From<#backing_type> for #id { + fn from(value: #backing_type) -> Self { + #id(value) + } + } + } + } else { + quote! { + #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + #[cfg_attr(feature = "serde", serde(try_from = #backing_type_str, into = #backing_type_str))] + pub struct #id(#backing_type); + + #common + + impl TryFrom<#backing_type> for #id { + type Error = #backing_type; + fn try_from(value: #backing_type) -> Result<Self, Self::Error> { + if value > #max_value { + Err(value) + } else { + Ok(#id(value)) + } + } + } + } + } +} + +fn generate_decl( + scope: &analyzer::Scope<'_>, + schema: &analyzer::Schema, + file: &ast::File, + decl: &ast::Decl, +) -> proc_macro2::TokenStream { + match &decl.desc { + ast::DeclDesc::Packet { id, .. } | ast::DeclDesc::Struct { id, .. } => { + match scope.get_parent(decl) { + None => generate_root_packet_decl(scope, schema, file.endianness.value, id), + Some(_) => generate_derived_packet_decl(scope, schema, file.endianness.value, id), + } + } + ast::DeclDesc::Enum { id, tags, width } => generate_enum_decl(id, tags, *width), + ast::DeclDesc::CustomField { id, width: Some(width), .. } => { + generate_custom_field_decl(file.endianness.value, id, *width) + } + ast::DeclDesc::CustomField { .. } => { + // No need to generate anything for a custom field, + // we just assume it will be in scope. + quote!() + } + _ => todo!("unsupported Decl::{:?}", decl), + } +} + +/// Generate Rust code from an AST. +/// +/// The code is not formatted, pipe it through `rustfmt` to get +/// readable source code. +pub fn generate_tokens( + sources: &ast::SourceDatabase, + file: &ast::File, + custom_fields: &[String], +) -> proc_macro2::TokenStream { + 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 schema = analyzer::Schema::new(file); + let custom_fields = custom_fields.iter().map(|custom_field| { + syn::parse_str::<syn::Path>(custom_field) + .unwrap_or_else(|err| panic!("invalid path '{custom_field}': {err:?}")) + }); + let decls = file.declarations.iter().map(|decl| generate_decl(&scope, &schema, file, decl)); + quote! { + #preamble + #(use #custom_fields;)* + + #(#decls)* + } +} + +/// Generate formatted Rust code from an AST. +/// +/// The code is not formatted, pipe it through `rustfmt` to get +/// readable source code. +pub fn generate( + sources: &ast::SourceDatabase, + file: &ast::File, + custom_fields: &[String], +) -> String { + let syntax_tree = + syn::parse2(generate_tokens(sources, file, custom_fields)).expect("Could not parse code"); + prettyplease::unparse(&syntax_tree) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::analyzer; + use crate::ast; + use crate::parser::parse_inline; + use crate::test_utils::{assert_snapshot_eq, format_rust}; + use paste::paste; + + /// Create a unit test for the given PDL `code`. + /// + /// The unit test will compare the generated Rust code for all + /// declarations with previously saved snapshots. The snapshots + /// are read from `"tests/generated/{name}_{endianness}_{id}.rs"` + /// where `is` taken from the declaration. + /// + /// When adding new tests or modifying existing ones, use + /// `UPDATE_SNAPSHOTS=1 cargo test` to automatically populate the + /// snapshots with the expected output. + /// + /// The `code` cannot have an endianness declaration, instead you + /// must supply either `little_endian` or `big_endian` as + /// `endianness`. + macro_rules! make_pdl_test { + ($name:ident, $code:expr, $endianness:ident) => { + paste! { + #[test] + fn [< test_ $name _ $endianness >]() { + let name = stringify!($name); + let endianness = stringify!($endianness); + let code = format!("{endianness}_packets\n{}", $code); + let mut db = ast::SourceDatabase::new(); + let file = parse_inline(&mut db, "test", code).unwrap(); + let file = analyzer::analyze(&file).unwrap(); + let actual_code = generate(&db, &file, &[]); + assert_snapshot_eq( + &format!("tests/generated/rust/{name}_{endianness}.rs"), + &format_rust(&actual_code), + ); + } + } + }; + } + + /// Create little- and bit-endian tests for the given PDL `code`. + /// + /// The `code` cannot have an endianness declaration: we will + /// automatically generate unit tests for both + /// "little_endian_packets" and "big_endian_packets". + macro_rules! test_pdl { + ($name:ident, $code:expr $(,)?) => { + make_pdl_test!($name, $code, little_endian); + make_pdl_test!($name, $code, big_endian); + }; + } + + test_pdl!(packet_decl_empty, "packet Foo {}"); + + test_pdl!(packet_decl_8bit_scalar, " packet Foo { x: 8 }"); + test_pdl!(packet_decl_24bit_scalar, "packet Foo { x: 24 }"); + test_pdl!(packet_decl_64bit_scalar, "packet Foo { x: 64 }"); + + test_pdl!( + enum_declaration, + r#" + enum IncompleteTruncatedClosed : 3 { + A = 0, + B = 1, + } + + enum IncompleteTruncatedOpen : 3 { + A = 0, + B = 1, + UNKNOWN = .. + } + + enum IncompleteTruncatedClosedWithRange : 3 { + A = 0, + B = 1..6 { + X = 1, + Y = 2, + } + } + + enum IncompleteTruncatedOpenWithRange : 3 { + A = 0, + B = 1..6 { + X = 1, + Y = 2, + }, + UNKNOWN = .. + } + + enum CompleteTruncated : 3 { + A = 0, + B = 1, + C = 2, + D = 3, + E = 4, + F = 5, + G = 6, + H = 7, + } + + enum CompleteTruncatedWithRange : 3 { + A = 0, + B = 1..7 { + X = 1, + Y = 2, + } + } + + enum CompleteWithRange : 8 { + A = 0, + B = 1, + C = 2..255, + } + "# + ); + + test_pdl!( + custom_field_declaration, + r#" + // Still unsupported. + // custom_field Dynamic "dynamic" + + // Should generate a type with From<u32> implementation. + custom_field ExactSize : 32 "exact_size" + + // Should generate a type with TryFrom<u32> implementation. + custom_field TruncatedSize : 24 "truncated_size" + "# + ); + + test_pdl!( + packet_decl_simple_scalars, + r#" + packet Foo { + x: 8, + y: 16, + z: 24, + } + "# + ); + + test_pdl!( + packet_decl_complex_scalars, + r#" + packet Foo { + a: 3, + b: 8, + c: 5, + d: 24, + e: 12, + f: 4, + } + "#, + ); + + // Test that we correctly mask a byte-sized value in the middle of + // a chunk. + test_pdl!( + packet_decl_mask_scalar_value, + r#" + packet Foo { + a: 2, + b: 24, + c: 6, + } + "#, + ); + + test_pdl!( + struct_decl_complex_scalars, + r#" + struct Foo { + a: 3, + b: 8, + c: 5, + d: 24, + e: 12, + f: 4, + } + "#, + ); + + test_pdl!(packet_decl_8bit_enum, " enum Foo : 8 { A = 1, B = 2 } packet Bar { x: Foo }"); + test_pdl!(packet_decl_24bit_enum, "enum Foo : 24 { A = 1, B = 2 } packet Bar { x: Foo }"); + test_pdl!(packet_decl_64bit_enum, "enum Foo : 64 { A = 1, B = 2 } packet Bar { x: Foo }"); + + test_pdl!( + packet_decl_mixed_scalars_enums, + " + enum Enum7 : 7 { + A = 1, + B = 2, + } + + enum Enum9 : 9 { + A = 1, + B = 2, + } + + packet Foo { + x: Enum7, + y: 5, + z: Enum9, + w: 3, + } + " + ); + + test_pdl!(packet_decl_8bit_scalar_array, " packet Foo { x: 8[3] }"); + test_pdl!(packet_decl_24bit_scalar_array, "packet Foo { x: 24[5] }"); + test_pdl!(packet_decl_64bit_scalar_array, "packet Foo { x: 64[7] }"); + + test_pdl!( + packet_decl_8bit_enum_array, + "enum Foo : 8 { FOO_BAR = 1, BAZ = 2 } packet Bar { x: Foo[3] }" + ); + test_pdl!( + packet_decl_24bit_enum_array, + "enum Foo : 24 { FOO_BAR = 1, BAZ = 2 } packet Bar { x: Foo[5] }" + ); + test_pdl!( + packet_decl_64bit_enum_array, + "enum Foo : 64 { FOO_BAR = 1, BAZ = 2 } packet Bar { x: Foo[7] }" + ); + + test_pdl!( + packet_decl_array_dynamic_count, + " + packet Foo { + _count_(x): 5, + padding: 3, + x: 24[] + } + " + ); + + test_pdl!( + packet_decl_array_dynamic_size, + " + packet Foo { + _size_(x): 5, + padding: 3, + x: 24[] + } + " + ); + + test_pdl!( + packet_decl_array_unknown_element_width_dynamic_size, + " + struct Foo { + _count_(a): 40, + a: 16[], + } + + packet Bar { + _size_(x): 40, + x: Foo[], + } + " + ); + + test_pdl!( + packet_decl_array_unknown_element_width_dynamic_count, + " + struct Foo { + _count_(a): 40, + a: 16[], + } + + packet Bar { + _count_(x): 40, + x: Foo[], + } + " + ); + + test_pdl!( + packet_decl_array_with_padding, + " + struct Foo { + _count_(a): 40, + a: 16[], + } + + packet Bar { + a: Foo[], + _padding_ [128], + } + " + ); + + test_pdl!( + packet_decl_array_dynamic_element_size, + " + struct Foo { + inner: 8[] + } + packet Bar { + _elementsize_(x): 5, + padding: 3, + x: Foo[] + } + " + ); + + test_pdl!( + packet_decl_array_dynamic_element_size_dynamic_size, + " + struct Foo { + inner: 8[] + } + packet Bar { + _size_(x): 4, + _elementsize_(x): 4, + x: Foo[] + } + " + ); + + test_pdl!( + packet_decl_array_dynamic_element_size_dynamic_count, + " + struct Foo { + inner: 8[] + } + packet Bar { + _count_(x): 4, + _elementsize_(x): 4, + x: Foo[] + } + " + ); + + test_pdl!( + packet_decl_array_dynamic_element_size_static_count, + " + struct Foo { + inner: 8[] + } + packet Bar { + _elementsize_(x): 5, + padding: 3, + x: Foo[4] + } + " + ); + + test_pdl!( + packet_decl_array_dynamic_element_size_static_count_1, + " + struct Foo { + inner: 8[] + } + packet Bar { + _elementsize_(x): 5, + padding: 3, + x: Foo[1] + } + " + ); + + test_pdl!( + packet_decl_reserved_field, + " + packet Foo { + _reserved_: 40, + } + " + ); + + test_pdl!( + packet_decl_custom_field, + r#" + custom_field Bar1 : 24 "exact" + custom_field Bar2 : 32 "truncated" + + packet Foo { + a: Bar1, + b: Bar2, + } + "# + ); + + test_pdl!( + packet_decl_fixed_scalar_field, + " + packet Foo { + _fixed_ = 7 : 7, + b: 57, + } + " + ); + + test_pdl!( + packet_decl_fixed_enum_field, + " + enum Enum7 : 7 { + A = 1, + B = 2, + } + + packet Foo { + _fixed_ = A : Enum7, + b: 57, + } + " + ); + + test_pdl!( + packet_decl_payload_field_variable_size, + " + packet Foo { + a: 8, + _size_(_payload_): 8, + _payload_, + b: 16, + } + " + ); + + test_pdl!( + packet_decl_payload_field_unknown_size, + " + packet Foo { + a: 24, + _payload_, + } + " + ); + + test_pdl!( + packet_decl_payload_field_unknown_size_terminal, + " + packet Foo { + _payload_, + a: 24, + } + " + ); + + test_pdl!( + packet_decl_child_packets, + " + enum Enum16 : 16 { + A = 1, + B = 2, + } + + packet Foo { + a: 8, + b: Enum16, + _size_(_payload_): 8, + _payload_ + } + + packet Bar : Foo (a = 100) { + x: 8, + } + + packet Baz : Foo (b = B) { + y: 16, + } + " + ); + + test_pdl!( + packet_decl_grand_children, + " + enum Enum16 : 16 { + A = 1, + B = 2, + } + + packet Parent { + foo: Enum16, + bar: Enum16, + baz: Enum16, + _size_(_payload_): 8, + _payload_ + } + + packet Child : Parent (foo = A) { + quux: Enum16, + _payload_, + } + + packet GrandChild : Child (bar = A, quux = A) { + _body_, + } + + packet GrandGrandChild : GrandChild (baz = A) { + _body_, + } + " + ); + + test_pdl!( + packet_decl_parent_with_no_payload, + " + enum Enum8 : 8 { + A = 0, + } + + packet Parent { + v : Enum8, + } + + packet Child : Parent (v = A) { + } + " + ); + + test_pdl!( + packet_decl_parent_with_alias_child, + " + enum Enum8 : 8 { + A = 0, + B = 1, + C = 2, + } + + packet Parent { + v : Enum8, + _payload_, + } + + packet AliasChild : Parent { + _payload_ + } + + packet NormalChild : Parent (v = A) { + } + + packet NormalGrandChild1 : AliasChild (v = B) { + } + + packet NormalGrandChild2 : AliasChild (v = C) { + _payload_ + } + " + ); + + test_pdl!( + reserved_identifier, + " + packet Test { + type: 8, + } + " + ); + + test_pdl!( + payload_with_size_modifier, + " + packet Test { + _size_(_payload_): 8, + _payload_ : [+1], + } + " + ); + + test_pdl!( + struct_decl_child_structs, + " + enum Enum16 : 16 { + A = 1, + B = 2, + } + + struct Foo { + a: 8, + b: Enum16, + _size_(_payload_): 8, + _payload_ + } + + struct Bar : Foo (a = 100) { + x: 8, + } + + struct Baz : Foo (b = B) { + y: 16, + } + " + ); + + test_pdl!( + struct_decl_grand_children, + " + enum Enum16 : 16 { + A = 1, + B = 2, + } + + struct Parent { + foo: Enum16, + bar: Enum16, + baz: Enum16, + _size_(_payload_): 8, + _payload_ + } + + struct Child : Parent (foo = A) { + quux: Enum16, + _payload_, + } + + struct GrandChild : Child (bar = A, quux = A) { + _body_, + } + + struct GrandGrandChild : GrandChild (baz = A) { + _body_, + } + " + ); +} diff --git a/src/backends/rust/parser.rs b/src/backends/rust/parser.rs index 8e76592..2d19fc9 100644 --- a/src/backends/rust/parser.rs +++ b/src/backends/rust/parser.rs @@ -12,14 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::analyzer::ast as analyzer_ast; -use crate::backends::rust::{ - constraint_to_value, find_constrained_parent_fields, mask_bits, types, ToIdent, - ToUpperCamelCase, -}; +use crate::backends::rust::{mask_bits, types, ToIdent, ToUpperCamelCase}; use crate::{analyzer, ast}; use quote::{format_ident, quote}; -use std::collections::{BTreeSet, HashMap}; fn size_field_ident(id: &str) -> proc_macro2::Ident { format_ident!("{}_size", id.trim_matches('_')) @@ -28,17 +23,18 @@ fn size_field_ident(id: &str) -> proc_macro2::Ident { /// A single bit-field. struct BitField<'a> { shift: usize, // The shift to apply to this field. - field: &'a analyzer_ast::Field, + field: &'a ast::Field, } pub struct FieldParser<'a> { scope: &'a analyzer::Scope<'a>, + schema: &'a analyzer::Schema, endianness: ast::EndiannessValue, - decl: &'a analyzer_ast::Decl, + decl: &'a ast::Decl, packet_name: &'a str, span: &'a proc_macro2::Ident, chunk: Vec<BitField<'a>>, - code: Vec<proc_macro2::TokenStream>, + tokens: proc_macro2::TokenStream, shift: usize, offset: usize, } @@ -46,24 +42,26 @@ pub struct FieldParser<'a> { impl<'a> FieldParser<'a> { pub fn new( scope: &'a analyzer::Scope<'a>, + schema: &'a analyzer::Schema, endianness: ast::EndiannessValue, packet_name: &'a str, span: &'a proc_macro2::Ident, ) -> FieldParser<'a> { FieldParser { scope, + schema, endianness, decl: scope.typedef[packet_name], packet_name, span, chunk: Vec::new(), - code: Vec::new(), + tokens: quote! {}, shift: 0, offset: 0, } } - pub fn add(&mut self, field: &'a analyzer_ast::Field) { + pub fn add(&mut self, field: &'a ast::Field) { match &field.desc { _ if field.cond.is_some() => self.add_optional_field(field), _ if self.scope.is_bitfield(field) => self.add_bit_field(field), @@ -73,7 +71,7 @@ impl<'a> FieldParser<'a> { *width, type_id.as_deref(), *size, - field.annot.padded_size, + self.schema.padded_size(field.key), self.scope.get_type_declaration(field), ), ast::FieldDesc::Typedef { id, type_id } => self.add_typedef_field(id, type_id), @@ -85,7 +83,7 @@ impl<'a> FieldParser<'a> { } } - fn add_optional_field(&mut self, field: &'a analyzer_ast::Field) { + fn add_optional_field(&mut self, field: &'a ast::Field) { let cond_id = field.cond.as_ref().unwrap().id.to_ident(); let cond_value = syn::parse_str::<syn::LitInt>(&format!( "{}", @@ -93,55 +91,55 @@ impl<'a> FieldParser<'a> { )) .unwrap(); - self.code.push( - match &field.desc { - ast::FieldDesc::Scalar { id, width } => { + self.tokens.extend(match &field.desc { + ast::FieldDesc::Scalar { id, width } => { + let id = id.to_ident(); + let value = types::get_uint(self.endianness, *width, self.span); + quote! { + let #id = (#cond_id == #cond_value).then(|| #value); + } + } + ast::FieldDesc::Typedef { id, type_id } => match &self.scope.typedef[type_id].desc { + ast::DeclDesc::Enum { width, .. } => { + let name = id; + let type_name = type_id; let id = id.to_ident(); + let type_id = type_id.to_ident(); + let decl_id = &self.packet_name; let value = types::get_uint(self.endianness, *width, self.span); quote! { - let #id = (#cond_id == #cond_value).then(|| #value); + let #id = (#cond_id == #cond_value) + .then(|| + #type_id::try_from(#value).map_err(|unknown_val| { + DecodeError::InvalidEnumValueError { + obj: #decl_id, + field: #name, + value: unknown_val as u64, + type_: #type_name, + } + })) + .transpose()?; } - }, - ast::FieldDesc::Typedef { id, type_id } => - match &self.scope.typedef[type_id].desc { - ast::DeclDesc::Enum { width, .. } => { - let name = id; - let type_name = type_id; - let id = id.to_ident(); - let type_id = type_id.to_ident(); - let decl_id = &self.packet_name; - let value = types::get_uint(self.endianness, *width, self.span); - quote! { - let #id = (#cond_id == #cond_value) - .then(|| - #type_id::try_from(#value).map_err(|unknown_val| Error::InvalidEnumValueError { - obj: #decl_id.to_string(), - field: #name.to_string(), - value: unknown_val as u64, - type_: #type_name.to_string(), - })) - .transpose()?; - } - } - ast::DeclDesc::Struct { .. } => { - let id = id.to_ident(); - let type_id = type_id.to_ident(); - let span = self.span; - quote! { - let #id = (#cond_id == #cond_value) - .then(|| #type_id::parse_inner(&mut #span)) - .transpose()?; - } - } - _ => unreachable!(), + } + ast::DeclDesc::Struct { .. } => { + let id = id.to_ident(); + let type_id = type_id.to_ident(); + let span = self.span; + quote! { + let #id = (#cond_id == #cond_value) + .then(|| #type_id::decode_mut(&mut #span)) + .transpose()?; } + } _ => unreachable!(), - }) + }, + _ => unreachable!(), + }) } - fn add_bit_field(&mut self, field: &'a analyzer_ast::Field) { + fn add_bit_field(&mut self, field: &'a ast::Field) { self.chunk.push(BitField { shift: self.shift, field }); - self.shift += field.annot.size.static_().unwrap(); + self.shift += self.schema.field_size(field.key).static_().unwrap(); if self.shift % 8 != 0 { return; } @@ -162,7 +160,7 @@ impl<'a> FieldParser<'a> { let get = types::get_uint(self.endianness, self.shift, self.span); if self.chunk.len() > 1 { // Multiple values: we read into a local variable. - self.code.push(quote! { + self.tokens.extend(quote! { let #chunk_name = #get; }); } @@ -182,7 +180,7 @@ impl<'a> FieldParser<'a> { v = quote! { (#v >> #shift) } } - let width = field.annot.size.static_().unwrap(); + let width = self.schema.field_size(field.key).static_().unwrap(); let value_type = types::Integer::new(width); if !single_value && width < value_type.width { // Mask value if we grabbed more than `width` and if @@ -195,7 +193,7 @@ impl<'a> FieldParser<'a> { v = quote! { #v as #value_type }; } - self.code.push(match &field.desc { + self.tokens.extend(match &field.desc { ast::FieldDesc::Scalar { id, .. } | ast::FieldDesc::Flag { id, .. } => { let id = id.to_ident(); @@ -209,7 +207,7 @@ impl<'a> FieldParser<'a> { quote! { let fixed_value = #v; if fixed_value != #value_type::from(#enum_id::#tag_id) { - return Err(Error::InvalidFixedValue { + return Err(DecodeError::InvalidFixedValue { expected: #value_type::from(#enum_id::#tag_id) as u64, actual: fixed_value as u64, }); @@ -221,7 +219,7 @@ impl<'a> FieldParser<'a> { quote! { let fixed_value = #v; if fixed_value != #value { - return Err(Error::InvalidFixedValue { + return Err(DecodeError::InvalidFixedValue { expected: #value, actual: fixed_value as u64, }); @@ -235,11 +233,11 @@ impl<'a> FieldParser<'a> { let id = id.to_ident(); let type_id = type_id.to_ident(); quote! { - let #id = #type_id::try_from(#v).map_err(|unknown_val| Error::InvalidEnumValueError { - obj: #packet_name.to_string(), - field: #field_name.to_string(), + let #id = #type_id::try_from(#v).map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: #packet_name, + field: #field_name, value: unknown_val as u64, - type_: #type_name.to_string(), + type_: #type_name, })?; } } @@ -248,7 +246,7 @@ impl<'a> FieldParser<'a> { let span = self.span; let size = proc_macro2::Literal::usize_unsuffixed(size); quote! { - #span.get_mut().advance(#size); + #span.advance(#size); } } else { // Otherwise we don't need anything: we will @@ -263,6 +261,12 @@ impl<'a> FieldParser<'a> { let #id = #v as usize; } } + ast::FieldDesc::ElementSize { field_id, .. } => { + let id = format_ident!("{field_id}_element_size"); + quote! { + let #id = #v as usize; + } + } ast::FieldDesc::Count { field_id, .. } => { let id = format_ident!("{field_id}_count"); quote! { @@ -291,6 +295,15 @@ impl<'a> FieldParser<'a> { } } + fn find_element_size_field(&self, id: &str) -> Option<proc_macro2::Ident> { + self.decl.fields().find_map(|field| match &field.desc { + ast::FieldDesc::ElementSize { field_id, .. } if field_id == id => { + Some(format_ident!("{id}_element_size")) + } + _ => None, + }) + } + fn payload_field_offset_from_end(&self) -> Option<usize> { let decl = self.scope.typedef[self.packet_name]; let mut fields = decl.fields(); @@ -300,7 +313,9 @@ impl<'a> FieldParser<'a> { let mut offset = 0; for field in fields { - if let Some(width) = field.annot.static_() { + if let Some(width) = + self.schema.padded_size(field.key).or(self.schema.field_size(field.key).static_()) + { offset += width; } else { return None; @@ -312,12 +327,12 @@ impl<'a> FieldParser<'a> { fn check_size(&mut self, span: &proc_macro2::Ident, wanted: &proc_macro2::TokenStream) { let packet_name = &self.packet_name; - self.code.push(quote! { - if #span.get().remaining() < #wanted { - return Err(Error::InvalidLengthError { - obj: #packet_name.to_string(), + self.tokens.extend(quote! { + if #span.remaining() < #wanted { + return Err(DecodeError::InvalidLengthError { + obj: #packet_name, wanted: #wanted, - got: #span.get().remaining(), + got: #span.remaining(), }); } }); @@ -335,18 +350,22 @@ impl<'a> FieldParser<'a> { // known). If None, the array is a Vec with a dynamic size. size: Option<usize>, padding_size: Option<usize>, - decl: Option<&analyzer_ast::Decl>, + decl: Option<&ast::Decl>, ) { enum ElementWidth { - Static(usize), // Static size in bytes. + Static(usize), // Static size in bytes. + Dynamic(proc_macro2::Ident), // Dynamic size in bytes. Unknown, } - let element_width = match width.or_else(|| decl.unwrap().annot.total_size().static_()) { - Some(w) => { - assert_eq!(w % 8, 0, "Array element size ({w}) is not a multiple of 8"); - ElementWidth::Static(w / 8) - } - None => ElementWidth::Unknown, + let element_width = if let Some(w) = + width.or_else(|| self.schema.total_size(decl.unwrap().key).static_()) + { + assert_eq!(w % 8, 0, "Array element size ({w}) is not a multiple of 8"); + ElementWidth::Static(w / 8) + } else if let Some(element_size_field) = self.find_element_size_field(id) { + ElementWidth::Dynamic(element_size_field) + } else { + ElementWidth::Unknown }; // The "shape" of the array, i.e., the number of elements @@ -373,17 +392,19 @@ impl<'a> FieldParser<'a> { let span = match padding_size { Some(padding_size) => { let span = self.span; - self.check_size(span, "e!(#padding_size)); - self.code.push(quote! { - let (head, tail) = #span.get().split_at(#padding_size); - let mut head = &mut Cell::new(head); - #span.replace(tail); + let padding_octets = padding_size / 8; + self.check_size(span, "e!(#padding_octets)); + self.tokens.extend(quote! { + let (mut head, tail) = #span.split_at(#padding_octets); + #span = tail; }); format_ident!("head") } None => self.span.clone(), }; + let field_name = id; + let packet_name = self.packet_name; let id = id.to_ident(); let parse_element = self.parse_array_element(&span, width, type_id, decl); @@ -395,12 +416,11 @@ impl<'a> FieldParser<'a> { self.check_size(&span, "e!(#size_field)); let parse_element = self.parse_array_element(&format_ident!("head"), width, type_id, decl); - self.code.push(quote! { - let (head, tail) = #span.get().split_at(#size_field); - let mut head = &mut Cell::new(head); - #span.replace(tail); + self.tokens.extend(quote! { + let (mut head, tail) = #span.split_at(#size_field); + #span = tail; let mut #id = Vec::new(); - while !head.get().is_empty() { + while !head.is_empty() { #id.push(#parse_element?); } }); @@ -409,34 +429,36 @@ impl<'a> FieldParser<'a> { // The element width is not known, but the array // element count is known statically. Parse elements // item by item as an array. - let count = syn::Index::from(*count); - self.code.push(quote! { + let count = proc_macro2::Literal::usize_unsuffixed(*count); + self.tokens.extend(quote! { // TODO(mgeisler): use // https://doc.rust-lang.org/std/array/fn.try_from_fn.html // when stabilized. - let #id = (0..#count) - .map(|_| #parse_element) - .collect::<Result<Vec<_>>>()? + let mut #id = Vec::with_capacity(#count); + for _ in 0..#count { + #id.push(#parse_element?) + } + let #id = #id .try_into() - .map_err(|_| Error::InvalidPacketError)?; + .map_err(|_| DecodeError::InvalidPacketError)?; }); } (ElementWidth::Unknown, ArrayShape::CountField(count_field)) => { // The element width is not known, but the array // element count is known by the count field. Parse // elements item by item as a vector. - self.code.push(quote! { + self.tokens.extend(quote! { let #id = (0..#count_field) .map(|_| #parse_element) - .collect::<Result<Vec<_>>>()?; + .collect::<Result<Vec<_>, DecodeError>>()?; }); } (ElementWidth::Unknown, ArrayShape::Unknown) => { // Neither the count not size is known, parse elements // until the end of the span. - self.code.push(quote! { + self.tokens.extend(quote! { let mut #id = Vec::new(); - while !#span.get().is_empty() { + while !#span.is_empty() { #id.push(#parse_element?); } }); @@ -444,34 +466,36 @@ impl<'a> FieldParser<'a> { (ElementWidth::Static(element_width), ArrayShape::Static(count)) => { // The element width is known, and the array element // count is known statically. - let count = syn::Index::from(*count); + let count = proc_macro2::Literal::usize_unsuffixed(*count); // This creates a nicely formatted size. let array_size = if element_width == 1 { quote!(#count) } else { - let element_width = syn::Index::from(element_width); + let element_width = proc_macro2::Literal::usize_unsuffixed(element_width); quote!(#count * #element_width) }; self.check_size(&span, "e! { #array_size }); - self.code.push(quote! { + self.tokens.extend(quote! { // TODO(mgeisler): use // https://doc.rust-lang.org/std/array/fn.try_from_fn.html // when stabilized. - let #id = (0..#count) - .map(|_| #parse_element) - .collect::<Result<Vec<_>>>()? + let mut #id = Vec::with_capacity(#count); + for _ in 0..#count { + #id.push(#parse_element?) + } + let #id = #id .try_into() - .map_err(|_| Error::InvalidPacketError)?; + .map_err(|_| DecodeError::InvalidPacketError)?; }); } (ElementWidth::Static(element_width), ArrayShape::CountField(count_field)) => { // The element width is known, and the array element // count is known dynamically by the count field. self.check_size(&span, "e!(#count_field * #element_width)); - self.code.push(quote! { + self.tokens.extend(quote! { let #id = (0..#count_field) .map(|_| #parse_element) - .collect::<Result<Vec<_>>>()?; + .collect::<Result<Vec<_>, DecodeError>>()?; }); } (ElementWidth::Static(element_width), ArrayShape::SizeField(_)) @@ -483,14 +507,14 @@ impl<'a> FieldParser<'a> { self.check_size(&span, "e!(#size_field)); quote!(#size_field) } else { - quote!(#span.get().remaining()) + quote!(#span.remaining()) }; let count_field = format_ident!("{id}_count"); let array_count = if element_width != 1 { - let element_width = syn::Index::from(element_width); - self.code.push(quote! { + let element_width = proc_macro2::Literal::usize_unsuffixed(element_width); + self.tokens.extend(quote! { if #array_size % #element_width != 0 { - return Err(Error::InvalidArraySize { + return Err(DecodeError::InvalidArraySize { array: #array_size, element: #element_width, }); @@ -502,13 +526,115 @@ impl<'a> FieldParser<'a> { array_size }; - self.code.push(quote! { + self.tokens.extend(quote! { let mut #id = Vec::with_capacity(#array_count); for _ in 0..#array_count { #id.push(#parse_element?); } }); } + (ElementWidth::Dynamic(element_size_field), ArrayShape::Static(count)) => { + // The element width is known, and the array element + // count is known statically. + let array_size = if *count == 1 { + quote!(#element_size_field) + } else { + quote!(#count * #element_size_field) + }; + + self.check_size(&span, &array_size); + + let parse_element = + self.parse_array_element(&format_ident!("chunk"), width, type_id, decl); + + self.tokens.extend(quote! { + // TODO: use + // https://doc.rust-lang.org/std/array/fn.try_from_fn.html + // when stabilized. + let #id = #span.chunks(#element_size_field) + .take(#count) + .map(|mut chunk| #parse_element.and_then(|value| { + if chunk.is_empty() { + Ok(value) + } else { + Err(DecodeError::TrailingBytesInArray { + obj: #packet_name, + field: #field_name, + }) + } + })) + .collect::<Result<Vec<_>, DecodeError>>()?; + #span = &#span[#array_size..]; + let #id = #id + .try_into() + .map_err(|_| DecodeError::InvalidPacketError)?; + }); + } + (ElementWidth::Dynamic(element_size_field), ArrayShape::CountField(count_field)) => { + // The element width is known, and the array element + // count is known dynamically by the count field. + self.check_size(&span, "e!(#count_field * #element_size_field)); + + let parse_element = + self.parse_array_element(&format_ident!("chunk"), width, type_id, decl); + + self.tokens.extend(quote! { + let #id = #span.chunks(#element_size_field) + .take(#count_field) + .map(|mut chunk| #parse_element.and_then(|value| { + if chunk.is_empty() { + Ok(value) + } else { + Err(DecodeError::TrailingBytesInArray { + obj: #packet_name, + field: #field_name, + }) + } + })) + .collect::<Result<Vec<_>, DecodeError>>()?; + #span = &#span[(#element_size_field * #count_field)..]; + }); + } + (ElementWidth::Dynamic(element_size_field), ArrayShape::SizeField(_)) + | (ElementWidth::Dynamic(element_size_field), ArrayShape::Unknown) => { + // The element width is known, and the array full size + // is known by size field, or unknown (in which case + // it is the remaining span length). + let array_size = if let ArrayShape::SizeField(size_field) = &array_shape { + self.check_size(&span, "e!(#size_field)); + quote!(#size_field) + } else { + quote!(#span.remaining()) + }; + self.tokens.extend(quote! { + if #array_size % #element_size_field != 0 { + return Err(DecodeError::InvalidArraySize { + array: #array_size, + element: #element_size_field, + }); + } + }); + + let parse_element = + self.parse_array_element(&format_ident!("chunk"), width, type_id, decl); + + self.tokens.extend(quote! { + let #id = #span.chunks(#element_size_field) + .take(#array_size / #element_size_field) + .map(|mut chunk| #parse_element.and_then(|value| { + if chunk.is_empty() { + Ok(value) + } else { + Err(DecodeError::TrailingBytesInArray { + obj: #packet_name, + field: #field_name, + }) + } + })) + .collect::<Result<Vec<_>, DecodeError>>()?; + #span = &#span[#array_size..]; + }); + } } } @@ -520,19 +646,15 @@ impl<'a> FieldParser<'a> { assert_eq!(self.shift, 0, "Typedef field does not start on an octet boundary"); let decl = self.scope.typedef[type_id]; - if let ast::DeclDesc::Struct { parent_id: Some(_), .. } = &decl.desc { - panic!("Derived struct used in typedef field"); - } - let span = self.span; let id = id.to_ident(); let type_id = type_id.to_ident(); - self.code.push(match decl.annot.size { - analyzer_ast::Size::Unknown | analyzer_ast::Size::Dynamic => quote! { - let #id = #type_id::parse_inner(&mut #span)?; + self.tokens.extend(match self.schema.decl_size(decl.key) { + analyzer::Size::Unknown | analyzer::Size::Dynamic => quote! { + let (#id, mut #span) = #type_id::decode(#span)?; }, - analyzer_ast::Size::Static(width) => { + analyzer::Size::Static(width) => { assert_eq!(width % 8, 0, "Typedef field type size is not a multiple of 8"); match &decl.desc { ast::DeclDesc::Checksum { .. } => todo!(), @@ -551,11 +673,8 @@ impl<'a> FieldParser<'a> { } } ast::DeclDesc::Struct { .. } => { - let width = syn::Index::from(width / 8); quote! { - let (head, tail) = #span.get().split_at(#width); - #span.replace(tail); - let #id = #type_id::parse(head)?; + let (#id, mut #span) = #type_id::decode(#span)?; } } _ => unreachable!(), @@ -587,10 +706,10 @@ impl<'a> FieldParser<'a> { // Push code to check that the size is greater than the size // modifier. Required to safely substract the modifier from the // size. - self.code.push(quote! { + self.tokens.extend(quote! { if #size_field < #size_modifier { - return Err(Error::InvalidLengthError { - obj: #packet_name.to_string(), + return Err(DecodeError::InvalidLengthError { + obj: #packet_name, wanted: #size_modifier, got: #size_field, }); @@ -599,16 +718,16 @@ impl<'a> FieldParser<'a> { }); } self.check_size(self.span, "e!(#size_field )); - self.code.push(quote! { - let payload = &#span.get()[..#size_field]; - #span.get_mut().advance(#size_field); + self.tokens.extend(quote! { + let payload = #span[..#size_field].to_vec(); + #span.advance(#size_field); }); } else if offset_from_end == Some(0) { // The payload or body is the last field of a packet, // consume the remaining span. - self.code.push(quote! { - let payload = #span.get(); - #span.get_mut().advance(payload.len()); + self.tokens.extend(quote! { + let payload = #span.to_vec(); + #span.advance(payload.len()); }); } else if let Some(offset_from_end) = offset_from_end { // The payload or body is followed by fields of static @@ -619,17 +738,17 @@ impl<'a> FieldParser<'a> { 0, "Payload field offset from end of packet is not a multiple of 8" ); - let offset_from_end = syn::Index::from(offset_from_end / 8); + let offset_from_end = proc_macro2::Literal::usize_unsuffixed(offset_from_end / 8); self.check_size(self.span, "e!(#offset_from_end)); - self.code.push(quote! { - let payload = &#span.get()[..#span.get().len() - #offset_from_end]; - #span.get_mut().advance(payload.len()); + self.tokens.extend(quote! { + let payload = #span[..#span.len() - #offset_from_end].to_vec(); + #span.advance(payload.len()); }); } let decl = self.scope.typedef[self.packet_name]; if let ast::DeclDesc::Struct { .. } = &decl.desc { - self.code.push(quote! { + self.tokens.extend(quote! { let payload = Vec::from(payload); }); } @@ -641,12 +760,12 @@ impl<'a> FieldParser<'a> { span: &proc_macro2::Ident, width: Option<usize>, type_id: Option<&str>, - decl: Option<&analyzer_ast::Decl>, + decl: Option<&ast::Decl>, ) -> proc_macro2::TokenStream { if let Some(width) = width { let get_uint = types::get_uint(self.endianness, width, span); return quote! { - Ok::<_, Error>(#get_uint) + Ok::<_, DecodeError>(#get_uint) }; } @@ -655,130 +774,25 @@ impl<'a> FieldParser<'a> { let type_id = id.to_ident(); let packet_name = &self.packet_name; return quote! { - #type_id::try_from(#get_uint).map_err(|unknown_val| Error::InvalidEnumValueError { - obj: #packet_name.to_string(), - field: String::new(), // TODO(mgeisler): fill out or remove + #type_id::try_from(#get_uint).map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: #packet_name, + field: "", // TODO(mgeisler): fill out or remove value: unknown_val as u64, - type_: #id.to_string(), + type_: #id, }) }; } let type_id = type_id.unwrap().to_ident(); quote! { - #type_id::parse_inner(#span) + #type_id::decode_mut(&mut #span) } } - - pub fn done(&mut self) { - let decl = self.scope.typedef[self.packet_name]; - if let ast::DeclDesc::Struct { .. } = &decl.desc { - 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() { - 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. - let constrained_fields = children - .iter() - .flat_map(|child| child.constraints().map(|c| &c.id)) - .collect::<BTreeSet<_>>(); - - let mut match_values = Vec::new(); - 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)) - }; - - for child in children.iter() { - let tuple_values = constrained_fields - .iter() - .map(|id| { - get_constraint_value(child.constraints(), id).map(|v| vec![v]).unwrap_or_else( - || { - self.scope - .file - .iter_children(child) - .filter_map(|d| get_constraint_value(d.constraints(), id)) - .collect() - }, - ) - }) - .collect::<Vec<_>>(); - - // If no constraint values are found for the tuple just skip the child - // packet as it would capture unwanted input packets. - if tuple_values.iter().all(|v| v.is_empty()) { - continue; - } - - let tuple_values = tuple_values - .iter() - .map(|v| v.is_empty().then_some(quote!(_)).unwrap_or_else(|| quote!( #(#v)|* ))) - .collect::<Vec<_>>(); - - let fields = find_constrained_parent_fields(self.scope, child.id().unwrap()) - .iter() - .map(|field| field.id().unwrap().to_ident()) - .collect::<Vec<_>>(); - - 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()); - } - - let constrained_field_idents = constrained_fields.iter().map(|field| field.to_ident()); - let packet_data_child = format_ident!("{}DataChild", self.packet_name); - - // Parsing of packet children requires having a payload field; - // it is allowed to inherit from a packet with empty payload, in this - // case generate an empty payload value. - if !decl - .fields() - .any(|f| matches!(&f.desc, ast::FieldDesc::Payload { .. } | ast::FieldDesc::Body)) - { - self.code.push(quote! { - let payload: &[u8] = &[]; - }) - } - self.code.push(quote! { - let child = match (#(#constrained_field_idents),*) { - #(#match_values if #child_ids_data::conforms(&payload) => { - let mut cell = Cell::new(payload); - let child_data = #child_ids_data::parse_inner(&mut cell #child_parse_args)?; - // TODO(mgeisler): communicate back to user if !cell.get().is_empty()? - #packet_data_child::#child_ids(child_data) - }),* - _ if !payload.is_empty() => { - #packet_data_child::Payload(Bytes::copy_from_slice(payload)) - } - _ => #packet_data_child::None, - }; - }); - } } impl quote::ToTokens for FieldParser<'_> { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { - let code = &self.code; - tokens.extend(quote! { - #(#code)* - }); + tokens.extend(self.tokens.clone()); } } @@ -794,7 +808,7 @@ mod tests { /// # Panics /// /// Panics on parse errors. - pub fn parse_str(text: &str) -> analyzer_ast::File { + pub fn parse_str(text: &str) -> ast::File { let mut db = ast::SourceDatabase::new(); let file = parse_inline(&mut db, "stdin", String::from(text)).expect("parse error"); analyzer::analyze(&file).expect("analyzer error") @@ -810,8 +824,9 @@ mod tests { "; let file = parse_str(code); let scope = analyzer::Scope::new(&file).unwrap(); + let schema = analyzer::Schema::new(&file); let span = format_ident!("bytes"); - let parser = FieldParser::new(&scope, file.endianness.value, "P", &span); + let parser = FieldParser::new(&scope, &schema, file.endianness.value, "P", &span); assert_eq!(parser.find_size_field("a"), None); assert_eq!(parser.find_count_field("a"), None); } @@ -827,8 +842,9 @@ mod tests { "; let file = parse_str(code); let scope = analyzer::Scope::new(&file).unwrap(); + let schema = analyzer::Schema::new(&file); let span = format_ident!("bytes"); - let parser = FieldParser::new(&scope, file.endianness.value, "P", &span); + let parser = FieldParser::new(&scope, &schema, file.endianness.value, "P", &span); assert_eq!(parser.find_size_field("b"), None); assert_eq!(parser.find_count_field("b"), Some(format_ident!("b_count"))); } @@ -844,8 +860,9 @@ mod tests { "; let file = parse_str(code); let scope = analyzer::Scope::new(&file).unwrap(); + let schema = analyzer::Schema::new(&file); let span = format_ident!("bytes"); - let parser = FieldParser::new(&scope, file.endianness.value, "P", &span); + let parser = FieldParser::new(&scope, &schema, file.endianness.value, "P", &span); assert_eq!(parser.find_size_field("c"), Some(format_ident!("c_size"))); assert_eq!(parser.find_count_field("c"), None); } diff --git a/src/backends/rust/preamble.rs b/src/backends/rust/preamble.rs index e9af398..bc64817 100644 --- a/src/backends/rust/preamble.rs +++ b/src/backends/rust/preamble.rs @@ -55,15 +55,14 @@ pub fn generate(path: &Path) -> proc_macro2::TokenStream { use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; - use pdl_runtime::{Error, Packet}; - - type Result<T> = std::result::Result<T, Error>; + use std::result::Result; + use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] + #[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { @@ -72,6 +71,12 @@ pub fn generate(path: &Path) -> proc_macro2::TokenStream { &self.0 } } + + impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } + } } } diff --git a/src/backends/rust/serializer.rs b/src/backends/rust/serializer.rs index b83f7c8..c4b88e0 100644 --- a/src/backends/rust/serializer.rs +++ b/src/backends/rust/serializer.rs @@ -12,131 +12,229 @@ // See the License for the specific language governing permissions and // 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 quote::{format_ident, quote}; -/// A single bit-field value. +/// Generate a range check for a scalar value backed to a rust type +/// that exceeds the actual size of the PDL field. +fn range_check( + value: proc_macro2::TokenStream, + width: usize, + packet_name: &str, + field_name: &str, +) -> proc_macro2::TokenStream { + let max_value = mask_bits(width, "u64"); + quote! { + if #value > #max_value { + return Err(EncodeError::InvalidScalarValue { + packet: #packet_name, + field: #field_name, + value: #value as u64, + maximum_value: #max_value as u64, + }) + } + } +} + +/// Represents the computed size of a packet, +/// compoased of constant and variable size fields. +struct RuntimeSize { + constant: usize, + variable: Vec<proc_macro2::TokenStream>, +} + +impl RuntimeSize { + fn payload_size() -> Self { + RuntimeSize { constant: 0, variable: vec![quote! { self.payload.len() }] } + } +} + +impl std::ops::AddAssign<&RuntimeSize> for RuntimeSize { + fn add_assign(&mut self, other: &RuntimeSize) { + self.constant += other.constant; + self.variable.extend_from_slice(&other.variable) + } +} + +impl quote::ToTokens for RuntimeSize { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let constant = proc_macro2::Literal::usize_unsuffixed(self.constant); + tokens.extend(match self { + RuntimeSize { variable, .. } if variable.is_empty() => quote! { #constant }, + RuntimeSize { variable, constant: 0 } => quote! { #(#variable)+* }, + RuntimeSize { variable, .. } => quote! { #constant + #(#variable)+* }, + }) + } +} + +/// Represents part of a compound bit-field. struct BitField { - value: proc_macro2::TokenStream, // An expression which produces a value. - field_type: types::Integer, // The type of the value. - shift: usize, // A bit-shift to apply to `value`. + value: proc_macro2::TokenStream, + field_type: types::Integer, + shift: usize, } -pub struct FieldSerializer<'a> { - scope: &'a analyzer::Scope<'a>, +struct Encoder { endianness: ast::EndiannessValue, - packet_name: &'a str, - span: &'a proc_macro2::Ident, - chunk: Vec<BitField>, - code: Vec<proc_macro2::TokenStream>, - shift: usize, + buf: proc_macro2::Ident, + packet_name: String, + packet_size: RuntimeSize, + payload_size: RuntimeSize, + tokens: proc_macro2::TokenStream, + bit_shift: usize, + bit_fields: Vec<BitField>, } -impl<'a> FieldSerializer<'a> { +impl Encoder { pub fn new( - scope: &'a analyzer::Scope<'a>, endianness: ast::EndiannessValue, - packet_name: &'a str, - span: &'a proc_macro2::Ident, - ) -> FieldSerializer<'a> { - FieldSerializer { - scope, + packet_name: &str, + buf: proc_macro2::Ident, + payload_size: RuntimeSize, + ) -> Self { + Encoder { + buf, + packet_name: packet_name.to_owned(), endianness, - packet_name, - span, - chunk: Vec::new(), - code: Vec::new(), - shift: 0, + packet_size: RuntimeSize { constant: 0, variable: vec![] }, + payload_size, + tokens: quote! {}, + bit_shift: 0, + bit_fields: vec![], } } - pub fn add(&mut self, field: &analyzer_ast::Field) { - match &field.desc { - _ if field.cond.is_some() => self.add_optional_field(field), - _ if self.scope.is_bitfield(field) => self.add_bit_field(field), - ast::FieldDesc::Array { id, width, .. } => self.add_array_field( - id, - *width, - field.annot.padded_size, - self.scope.get_type_declaration(field), - ), - ast::FieldDesc::Typedef { id, type_id } => { - self.add_typedef_field(id, type_id); - } - ast::FieldDesc::Payload { .. } | ast::FieldDesc::Body { .. } => { - self.add_payload_field(); + fn encode_typedef_field( + &mut self, + scope: &analyzer::Scope<'_>, + schema: &analyzer::Schema, + id: &str, + type_id: &str, + ) { + assert_eq!(self.bit_shift, 0, "Typedef field does not start on an octet boundary"); + + let decl = scope.typedef[type_id]; + let id = id.to_ident(); + let buf = &self.buf; + + self.tokens.extend(match &decl.desc { + ast::DeclDesc::Checksum { .. } => todo!(), + ast::DeclDesc::CustomField { width: Some(width), .. } => { + let backing_type = types::Integer::new(*width); + let put_uint = types::put_uint( + self.endianness, + "e! { #backing_type::from(self.#id) }, + *width, + &self.buf, + ); + quote! { + #put_uint; + } } - // Padding field handled in serialization of associated array field. - ast::FieldDesc::Padding { .. } => (), - _ => todo!("Cannot yet serialize {field:?}"), + ast::DeclDesc::Struct { .. } | ast::DeclDesc::CustomField { .. } => quote! { + self.#id.encode(#buf)?; + }, + _ => todo!("{:?}", decl), + }); + + match schema.decl_size(decl.key) { + analyzer::Size::Static(s) => self.packet_size.constant += s, + _ => self.packet_size.variable.push(quote! { self.#id.encoded_len() }), } } - fn add_optional_field(&mut self, field: &analyzer_ast::Field) { - self.code.push(match &field.desc { + fn encode_optional_field( + &mut self, + scope: &analyzer::Scope<'_>, + _schema: &analyzer::Schema, + field: &ast::Field, + ) { + assert_eq!(self.bit_shift, 0, "Optional field does not start on an octet boundary"); + + self.tokens.extend(match &field.desc { ast::FieldDesc::Scalar { id, width } => { - let name = id; + let field_name = id; let id = id.to_ident(); let backing_type = types::Integer::new(*width); - let write = types::put_uint(self.endianness, "e!(*#id), *width, self.span); - - let range_check = (backing_type.width > *width).then(|| { - let packet_name = &self.packet_name; - let max_value = mask_bits(*width, "u64"); - - quote! { - if *#id > #max_value { - panic!( - "Invalid value for {}::{}: {} > {}", - #packet_name, #name, #id, #max_value - ); - } - } - }); - + let put_uint = types::put_uint(self.endianness, "e!(*#id), *width, &self.buf); + let range_check = (backing_type.width > *width) + .then(|| range_check(quote! { *#id }, *width, &self.packet_name, field_name)); quote! { if let Some(#id) = &self.#id { #range_check - #write + #put_uint; } } } - ast::FieldDesc::Typedef { id, type_id } => match &self.scope.typedef[type_id].desc { + ast::FieldDesc::Typedef { id, type_id } => match &scope.typedef[type_id].desc { ast::DeclDesc::Enum { width, .. } => { let id = id.to_ident(); let backing_type = types::Integer::new(*width); - let write = types::put_uint( + let put_uint = types::put_uint( self.endianness, "e!(#backing_type::from(#id)), *width, - self.span, + &self.buf, ); + quote! { if let Some(#id) = &self.#id { - #write + #put_uint; } } } ast::DeclDesc::Struct { .. } => { let id = id.to_ident(); - let span = self.span; + let buf = &self.buf; + quote! { if let Some(#id) = &self.#id { - #id.write_to(#span); + #id.encode(#buf)?; } } } _ => unreachable!(), }, _ => unreachable!(), + }); + + self.packet_size.variable.push(match &field.desc { + ast::FieldDesc::Scalar { id, width } => { + let id = id.to_ident(); + let size = width / 8; + quote! { if self.#id.is_some() { #size } else { 0 } } + } + ast::FieldDesc::Typedef { id, type_id } => match &scope.typedef[type_id].desc { + ast::DeclDesc::Enum { width, .. } => { + let id = id.to_ident(); + let size = width / 8; + quote! { if self.#id.is_some() { #size } else { 0 } } + } + ast::DeclDesc::Struct { .. } => { + let id = id.to_ident(); + let type_id = type_id.to_ident(); + quote! { + &self.#id + .as_ref() + .map(#type_id::encoded_len) + .unwrap_or(0) + } + } + _ => unreachable!(), + }, + _ => unreachable!(), }) } - fn add_bit_field(&mut self, field: &analyzer_ast::Field) { - let width = field.annot.size.static_().unwrap(); - let shift = self.shift; + fn encode_bit_field( + &mut self, + scope: &analyzer::Scope<'_>, + schema: &analyzer::Schema, + field: &ast::Field, + ) { + let width = schema.field_size(field.key).static_().unwrap(); + let shift = self.bit_shift; match &field.desc { ast::FieldDesc::Flag { optional_field_id, set_value, .. } => { @@ -145,7 +243,7 @@ impl<'a> FieldSerializer<'a> { syn::parse_str::<syn::LitInt>(&format!("{}", set_value)).unwrap(); let cond_value_absent = syn::parse_str::<syn::LitInt>(&format!("{}", 1 - set_value)).unwrap(); - self.chunk.push(BitField { + self.bit_fields.push(BitField { value: quote! { if self.#optional_field_id.is_some() { #cond_value_present @@ -158,27 +256,28 @@ impl<'a> FieldSerializer<'a> { }); } ast::FieldDesc::Scalar { id, width } => { - let field_name = id.to_ident(); + let field_name = id; + let field_id = id.to_ident(); let field_type = types::Integer::new(*width); if field_type.width > *width { - let packet_name = &self.packet_name; - let max_value = mask_bits(*width, "u64"); - self.code.push(quote! { - if self.#field_name > #max_value { - panic!( - "Invalid value for {}::{}: {} > {}", - #packet_name, #id, self.#field_name, #max_value - ); - } - }); + self.tokens.extend(range_check( + quote! { self.#field_id() }, + *width, + &self.packet_name, + field_name, + )); } - self.chunk.push(BitField { value: quote!(self.#field_name), field_type, shift }); + self.bit_fields.push(BitField { + value: quote! { self.#field_id() }, + field_type, + shift, + }); } ast::FieldDesc::FixedEnum { enum_id, tag_id, .. } => { let field_type = types::Integer::new(width); let enum_id = enum_id.to_ident(); let tag_id = format_ident!("{}", tag_id.to_upper_camel_case()); - self.chunk.push(BitField { + self.bit_fields.push(BitField { value: quote!(#field_type::from(#enum_id::#tag_id)), field_type, shift, @@ -187,13 +286,13 @@ impl<'a> FieldSerializer<'a> { ast::FieldDesc::FixedScalar { value, .. } => { let field_type = types::Integer::new(width); let value = proc_macro2::Literal::usize_unsuffixed(*value); - self.chunk.push(BitField { value: quote!(#value), field_type, shift }); + self.bit_fields.push(BitField { value: quote!(#value), field_type, shift }); } ast::FieldDesc::Typedef { id, .. } => { - let field_name = id.to_ident(); + let id = id.to_ident(); let field_type = types::Integer::new(width); - self.chunk.push(BitField { - value: quote!(#field_type::from(self.#field_name)), + self.bit_fields.push(BitField { + value: quote!(#field_type::from(self.#id())), field_type, shift, }); @@ -205,9 +304,8 @@ impl<'a> FieldSerializer<'a> { let packet_name = &self.packet_name; let max_value = mask_bits(*width, "usize"); - let decl = self.scope.typedef.get(self.packet_name).unwrap(); - let value_field = self - .scope + let decl = scope.typedef.get(&self.packet_name).unwrap(); + let value_field = scope .iter_fields(decl) .find(|field| match &field.desc { ast::FieldDesc::Payload { .. } => field_id == "_payload_", @@ -220,9 +318,7 @@ impl<'a> FieldSerializer<'a> { let field_type = types::Integer::new(*width); // TODO: size modifier - let value_field_decl = self.scope.get_type_declaration(value_field); - - let field_size_name = format_ident!("{field_id}_size"); + let value_field_decl = scope.get_type_declaration(value_field); let array_size = match (&value_field.desc, value_field_decl.map(|decl| &decl.desc)) { (ast::FieldDesc::Payload { size_modifier: Some(size_modifier) }, _) => { @@ -231,33 +327,29 @@ impl<'a> FieldSerializer<'a> { .parse::<usize>() .expect("failed to parse the size modifier"), ); - if let ast::DeclDesc::Packet { .. } = &decl.desc { - quote! { (self.child.get_total_size() + #size_modifier) } - } else { - quote! { (self.payload.len() + #size_modifier) } - } + let payload_size = &self.payload_size; + quote! { (#payload_size + #size_modifier) } } (ast::FieldDesc::Payload { .. } | ast::FieldDesc::Body { .. }, _) => { - if let ast::DeclDesc::Packet { .. } = &decl.desc { - quote! { self.child.get_total_size() } - } else { - quote! { self.payload.len() } - } + let payload_size = &self.payload_size; + quote! { #payload_size } } (ast::FieldDesc::Array { width: Some(width), .. }, _) | (ast::FieldDesc::Array { .. }, Some(ast::DeclDesc::Enum { width, .. })) => { - let byte_width = syn::Index::from(width / 8); - if byte_width.index == 1 { + let size = width / 8; + if size == 1 { quote! { self.#field_name.len() } } else { - quote! { (self.#field_name.len() * #byte_width) } + let size = proc_macro2::Literal::usize_unsuffixed(size); + quote! { (self.#field_name.len() * #size) } } } (ast::FieldDesc::Array { .. }, _) => { - self.code.push(quote! { + let field_size_name = format_ident!("{field_id}_size"); + self.tokens.extend(quote! { let #field_size_name = self.#field_name .iter() - .map(|elem| elem.get_size()) + .map(Packet::encoded_len) .sum::<usize>(); }); quote! { #field_size_name } @@ -265,37 +357,79 @@ impl<'a> FieldSerializer<'a> { _ => panic!("Unexpected size field: {field:?}"), }; - self.code.push(quote! { + self.tokens.extend(quote! { if #array_size > #max_value { - panic!( - "Invalid length for {}::{}: {} > {}", - #packet_name, #field_id, #array_size, #max_value - ); + return Err(EncodeError::SizeOverflow { + packet: #packet_name, + field: #field_id, + size: #array_size, + maximum_size: #max_value, + }) } }); - self.chunk.push(BitField { + self.bit_fields.push(BitField { value: quote!(#array_size as #field_type), field_type, shift, }); } + ast::FieldDesc::ElementSize { field_id, width, .. } => { + let field_name = field_id.to_ident(); + let field_type = types::Integer::new(*width); + let field_element_size_name = format_ident!("{field_id}_element_size"); + let packet_name = &self.packet_name; + let max_value = mask_bits(*width, "usize"); + self.tokens.extend(quote! { + let #field_element_size_name = self.#field_name + .get(0) + .map_or(0, Packet::encoded_len); + + for (element_index, element) in self.#field_name.iter().enumerate() { + if element.encoded_len() != #field_element_size_name { + return Err(EncodeError::InvalidArrayElementSize { + packet: #packet_name, + field: #field_id, + size: element.encoded_len(), + expected_size: #field_element_size_name, + element_index, + }) + } + } + if #field_element_size_name > #max_value { + return Err(EncodeError::SizeOverflow { + packet: #packet_name, + field: #field_id, + size: #field_element_size_name, + maximum_size: #max_value, + }) + } + let #field_element_size_name = #field_element_size_name as #field_type; + }); + self.bit_fields.push(BitField { + value: quote!(#field_element_size_name), + field_type, + shift, + }); + } ast::FieldDesc::Count { field_id, width, .. } => { let field_name = field_id.to_ident(); let field_type = types::Integer::new(*width); if field_type.width > *width { let packet_name = &self.packet_name; let max_value = mask_bits(*width, "usize"); - self.code.push(quote! { + self.tokens.extend(quote! { if self.#field_name.len() > #max_value { - panic!( - "Invalid length for {}::{}: {} > {}", - #packet_name, #field_id, self.#field_name.len(), #max_value - ); + return Err(EncodeError::CountOverflow { + packet: #packet_name, + field: #field_id, + count: self.#field_name.len(), + maximum_count: #max_value, + }) } }); } - self.chunk.push(BitField { + self.bit_fields.push(BitField { value: quote!(self.#field_name.len() as #field_type), field_type, shift, @@ -304,17 +438,17 @@ impl<'a> FieldSerializer<'a> { _ => todo!("{field:?}"), } - self.shift += width; - if self.shift % 8 == 0 { + self.bit_shift += width; + if self.bit_shift % 8 == 0 { self.pack_bit_fields() } } fn pack_bit_fields(&mut self) { - assert_eq!(self.shift % 8, 0); - let chunk_type = types::Integer::new(self.shift); + assert_eq!(self.bit_shift % 8, 0); + let chunk_type = types::Integer::new(self.bit_shift); let values = self - .chunk + .bit_fields .drain(..) .map(|BitField { mut value, field_type, shift }| { if field_type.width != chunk_type.width { @@ -331,44 +465,52 @@ impl<'a> FieldSerializer<'a> { }) .collect::<Vec<_>>(); - match values.as_slice() { + self.tokens.extend(match values.as_slice() { [] => { - let span = format_ident!("{}", self.span); - let count = syn::Index::from(self.shift / 8); - self.code.push(quote! { - #span.put_bytes(0, #count); - }); + let buf = format_ident!("{}", self.buf); + let count = proc_macro2::Literal::usize_unsuffixed(self.bit_shift / 8); + quote! { + #buf.put_bytes(0, #count); + } } [value] => { - let put = types::put_uint(self.endianness, value, self.shift, self.span); - self.code.push(quote! { + let put = types::put_uint(self.endianness, value, self.bit_shift, &self.buf); + quote! { #put; - }); + } } _ => { - let put = types::put_uint(self.endianness, "e!(value), self.shift, self.span); - self.code.push(quote! { + let put = + types::put_uint(self.endianness, "e!(value), self.bit_shift, &self.buf); + quote! { let value = #(#values)|*; #put; - }); + } } - } + }); - self.shift = 0; + self.packet_size.constant += self.bit_shift / 8; + self.bit_shift = 0; } - fn add_array_field( + fn encode_array_field( &mut self, + _scope: &analyzer::Scope<'_>, + schema: &analyzer::Schema, id: &str, width: Option<usize>, padding_size: Option<usize>, - decl: Option<&analyzer_ast::Decl>, + decl: Option<&ast::Decl>, ) { - let span = format_ident!("{}", self.span); - let serialize = match width { + assert_eq!(self.bit_shift, 0, "Array field does not start on an octet boundary"); + + let buf = &self.buf; + + // Code to encode one array element. + let put_element = match width { Some(width) => { let value = quote!(*elem); - types::put_uint(self.endianness, &value, width, self.span) + types::put_uint(self.endianness, &value, width, &self.buf) } None => { if let Some(ast::DeclDesc::Enum { width, .. }) = decl.map(|decl| &decl.desc) { @@ -377,112 +519,175 @@ impl<'a> FieldSerializer<'a> { self.endianness, "e!(#element_type::from(elem)), *width, - self.span, + &self.buf, ) } else { quote! { - elem.write_to(#span) + elem.encode(#buf)? } } } }; + let packet_name = &self.packet_name; + let field_name = id; let id = id.to_ident(); - self.code.push(match padding_size { - Some(padding_size) => - quote! { - let current_size = #span.len(); - for elem in &self.#id { - #serialize; - } - let array_size = #span.len() - current_size; - if array_size > #padding_size { - panic!("attempted to serialize an array larger than the enclosing padding size"); - } - #span.put_bytes(0, #padding_size - array_size); - }, - None => + let element_width = match &width { + Some(width) => Some(*width), + None => schema.decl_size(decl.unwrap().key).static_(), + }; + + let array_size = match element_width { + Some(element_width) => { + let element_size = proc_macro2::Literal::usize_unsuffixed(element_width / 8); + quote! { self.#id.len() * #element_size } + } + _ => { quote! { - for elem in &self.#id { - #serialize; - } + self.#id + .iter() + .map(Packet::encoded_len) + .sum::<usize>() } - }); - } - - fn add_typedef_field(&mut self, id: &str, type_id: &str) { - assert_eq!(self.shift, 0, "Typedef field does not start on an octet boundary"); - let decl = self.scope.typedef[type_id]; - if let ast::DeclDesc::Struct { parent_id: Some(_), .. } = &decl.desc { - panic!("Derived struct used in typedef field"); - } - - let id = id.to_ident(); - let span = format_ident!("{}", self.span); + } + }; - self.code.push(match &decl.desc { - ast::DeclDesc::Checksum { .. } => todo!(), - ast::DeclDesc::CustomField { width: Some(width), .. } => { - let backing_type = types::Integer::new(*width); - let put_uint = types::put_uint( - self.endianness, - "e! { #backing_type::from(self.#id) }, - *width, - self.span, - ); - quote! { - #put_uint; + self.tokens.extend(if let Some(padding_size) = padding_size { + let padding_octets = padding_size / 8; + quote! { + let array_size = #array_size; + if array_size > #padding_octets { + return Err(EncodeError::SizeOverflow { + packet: #packet_name, + field: #field_name, + size: array_size, + maximum_size: #padding_octets, + }) + } + for elem in &self.#id { + #put_element; + } + #buf.put_bytes(0, #padding_octets - array_size); + } + } else { + quote! { + for elem in &self.#id { + #put_element; } } - ast::DeclDesc::Struct { .. } => quote! { - self.#id.write_to(#span); - }, - _ => unreachable!(), }); + + self.packet_size.variable.push(array_size) } - fn add_payload_field(&mut self) { - if self.shift != 0 && self.endianness == ast::EndiannessValue::BigEndian { - panic!("Payload field does not start on an octet boundary"); + fn encode_field( + &mut self, + scope: &analyzer::Scope<'_>, + schema: &analyzer::Schema, + payload: &proc_macro2::TokenStream, + field: &ast::Field, + ) { + match &field.desc { + _ if field.cond.is_some() => self.encode_optional_field(scope, schema, field), + _ if scope.is_bitfield(field) => self.encode_bit_field(scope, schema, field), + ast::FieldDesc::Array { id, width, .. } => self.encode_array_field( + scope, + schema, + id, + *width, + schema.padded_size(field.key), + scope.get_type_declaration(field), + ), + ast::FieldDesc::Typedef { id, type_id } => { + self.encode_typedef_field(scope, schema, id, type_id) + } + ast::FieldDesc::Payload { .. } | ast::FieldDesc::Body { .. } => { + self.tokens.extend(payload.clone()); + self.packet_size += &self.payload_size + } + // Padding field handled in serialization of associated array field. + ast::FieldDesc::Padding { .. } => (), + _ => todo!("Cannot yet serialize {field:?}"), } + } +} - let decl = self.scope.typedef[self.packet_name]; - let is_packet = matches!(&decl.desc, ast::DeclDesc::Packet { .. }); - - let child_ids = self - .scope - .iter_children(decl) - .map(|child| child.id().unwrap().to_ident()) - .collect::<Vec<_>>(); +fn encode_with_parents( + scope: &analyzer::Scope<'_>, + schema: &analyzer::Schema, + endianness: ast::EndiannessValue, + buf: proc_macro2::Ident, + decl: &ast::Decl, + payload_size: RuntimeSize, + payload: proc_macro2::TokenStream, +) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) { + let packet_name = decl.id().unwrap(); + let mut encoder = Encoder::new(endianness, packet_name, buf.clone(), payload_size); + for field in decl.fields() { + encoder.encode_field(scope, schema, &payload, field); + } - let span = format_ident!("{}", self.span); - if self.shift == 0 { - if is_packet { - let packet_data_child = format_ident!("{}DataChild", self.packet_name); - self.code.push(quote! { - match &self.child { - #(#packet_data_child::#child_ids(child) => child.write_to(#span),)* - #packet_data_child::Payload(payload) => #span.put_slice(payload), - #packet_data_child::None => {}, - } - }) - } else { - self.code.push(quote! { - #span.put_slice(&self.payload); - }); - } - } else { - todo!("Shifted payloads"); + match scope.get_parent(decl) { + Some(parent_decl) => encode_with_parents( + scope, + schema, + endianness, + buf, + parent_decl, + encoder.packet_size, + encoder.tokens, + ), + None => { + let packet_size = encoder.packet_size; + (encoder.tokens, quote! { #packet_size }) } } } -impl quote::ToTokens for FieldSerializer<'_> { - fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { - let code = &self.code; - tokens.extend(quote! { - #(#code)* - }); +pub fn encode( + scope: &analyzer::Scope<'_>, + schema: &analyzer::Schema, + endianness: ast::EndiannessValue, + buf: proc_macro2::Ident, + decl: &ast::Decl, +) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) { + encode_with_parents( + scope, + schema, + endianness, + buf.clone(), + decl, + RuntimeSize::payload_size(), + quote! { #buf.put_slice(&self.payload); }, + ) +} + +pub fn encode_partial( + scope: &analyzer::Scope<'_>, + schema: &analyzer::Schema, + endianness: ast::EndiannessValue, + buf: proc_macro2::Ident, + decl: &ast::Decl, +) -> (proc_macro2::TokenStream, proc_macro2::TokenStream, proc_macro2::TokenStream) { + let parent_decl = scope.get_parent(decl).unwrap(); + + let mut encoder = + Encoder::new(endianness, decl.id().unwrap(), buf.clone(), RuntimeSize::payload_size()); + + for field in decl.fields() { + encoder.encode_field(scope, schema, "e! { #buf.put_slice(&self.payload); }, field); } + + let (encode_parents, encoded_len) = encode_with_parents( + scope, + schema, + endianness, + buf, + parent_decl, + encoder.packet_size, + quote! { self.encode_partial(buf)?; }, + ); + + (encoder.tokens, encode_parents, encoded_len) } diff --git a/src/backends/rust/test.rs b/src/backends/rust/test.rs new file mode 100644 index 0000000..0805024 --- /dev/null +++ b/src/backends/rust/test.rs @@ -0,0 +1,255 @@ +// 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. + +//! Generate Rust unit tests for canonical test vectors. + +use quote::{format_ident, quote}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; + +#[derive(Debug, Deserialize)] +struct Packet { + #[serde(rename = "packet")] + name: String, + tests: Vec<TestVector>, +} + +#[derive(Debug, Deserialize)] +struct TestVector { + packed: String, + unpacked: Value, + packet: Option<String>, +} + +/// Convert a string of hexadecimal characters into a Rust vector of +/// bytes. +/// +/// The string `"80038302"` becomes `vec![0x80, 0x03, 0x83, 0x02]`. +fn hexadecimal_to_vec(hex: &str) -> proc_macro2::TokenStream { + assert!(hex.len() % 2 == 0, "Expects an even number of hex digits"); + let bytes = hex.as_bytes().chunks_exact(2).map(|chunk| { + let number = format!("0x{}", std::str::from_utf8(chunk).unwrap()); + syn::parse_str::<syn::LitInt>(&number).unwrap() + }); + + quote! { + vec![#(#bytes),*] + } +} + +/// Convert `value` to a JSON string literal. +/// +/// The string literal is a raw literal to avoid escaping +/// double-quotes. +fn to_json<T: Serialize>(value: &T) -> syn::LitStr { + let json = serde_json::to_string(value).unwrap(); + assert!(!json.contains("\"#"), "Please increase number of # for {json:?}"); + syn::parse_str::<syn::LitStr>(&format!("r#\" {json} \"#")).unwrap() +} + +fn generate_unit_tests(input: &str, packet_names: &[&str]) -> Result<String, String> { + eprintln!("Reading test vectors from {input}, will use {} packets", packet_names.len()); + + let data = std::fs::read_to_string(input) + .unwrap_or_else(|err| panic!("Could not read {input}: {err}")); + let packets: Vec<Packet> = serde_json::from_str(&data).expect("Could not parse JSON"); + + let mut tests = Vec::new(); + for packet in &packets { + for (i, test_vector) in packet.tests.iter().enumerate() { + let test_packet = test_vector.packet.as_deref().unwrap_or(packet.name.as_str()); + if !packet_names.contains(&test_packet) { + eprintln!("Skipping packet {}", test_packet); + continue; + } + eprintln!("Generating tests for packet {}", test_packet); + + let parse_test_name = format_ident!( + "test_parse_{}_vector_{}_0x{}", + test_packet, + i + 1, + &test_vector.packed + ); + let serialize_test_name = format_ident!( + "test_serialize_{}_vector_{}_0x{}", + test_packet, + i + 1, + &test_vector.packed + ); + let packed = hexadecimal_to_vec(&test_vector.packed); + let packet_name = format_ident!("{}", test_packet); + + let object = test_vector.unpacked.as_object().unwrap_or_else(|| { + panic!("Expected test vector object, found: {}", test_vector.unpacked) + }); + let assertions = object.iter().map(|(key, value)| { + let getter = format_ident!("{key}"); + let expected = format_ident!("expected_{key}"); + let json = to_json(&value); + quote! { + let #expected: serde_json::Value = serde_json::from_str(#json) + .expect("Could not create expected value from canonical JSON data"); + assert_eq!(json!(actual.#getter()), #expected); + } + }); + + let json = to_json(&object); + tests.push(quote! { + #[test] + fn #parse_test_name() { + let packed = #packed; + let actual = #packet_name::decode_full(&packed).unwrap(); + #(#assertions)* + } + + #[test] + fn #serialize_test_name() { + let packet: #packet_name = serde_json::from_str(#json) + .expect("Could not create packet from canonical JSON data"); + let packed: Vec<u8> = #packed; + assert_eq!(packet.encode_to_vec(), Ok(packed)); + } + }); + } + } + + // TODO(mgeisler): make the generated code clean from warnings. + let code = quote! { + #[allow(warnings, missing_docs)] + #[cfg(test)] + mod test { + use pdl_runtime::Packet; + use serde_json::json; + use super::*; + + #(#tests)* + } + }; + let syntax_tree = syn::parse2::<syn::File>(code).expect("Could not parse {code:#?}"); + Ok(prettyplease::unparse(&syntax_tree)) +} + +pub fn generate_tests(input_file: &str) -> Result<String, String> { + // TODO(mgeisler): remove the `packet_names` argument when we + // support all canonical packets. + generate_unit_tests( + input_file, + &[ + "EnumChild_A", + "EnumChild_B", + "Packet_Array_Field_ByteElement_ConstantSize", + "Packet_Array_Field_ByteElement_UnknownSize", + "Packet_Array_Field_ByteElement_VariableCount", + "Packet_Array_Field_ByteElement_VariableSize", + "Packet_Array_Field_EnumElement", + "Packet_Array_Field_EnumElement_ConstantSize", + "Packet_Array_Field_EnumElement_UnknownSize", + "Packet_Array_Field_EnumElement_VariableCount", + "Packet_Array_Field_EnumElement_VariableCount", + "Packet_Array_Field_ScalarElement", + "Packet_Array_Field_ScalarElement_ConstantSize", + "Packet_Array_Field_ScalarElement_UnknownSize", + "Packet_Array_Field_ScalarElement_VariableCount", + "Packet_Array_Field_ScalarElement_VariableSize", + "Packet_Array_Field_SizedElement_ConstantSize", + "Packet_Array_Field_SizedElement_UnknownSize", + "Packet_Array_Field_SizedElement_VariableCount", + "Packet_Array_Field_SizedElement_VariableSize", + "Packet_Array_Field_UnsizedElement_ConstantSize", + "Packet_Array_Field_UnsizedElement_UnknownSize", + "Packet_Array_Field_UnsizedElement_VariableCount", + "Packet_Array_Field_UnsizedElement_VariableSize", + "Packet_Array_Field_SizedElement_VariableSize_Padded", + "Packet_Array_Field_UnsizedElement_VariableCount_Padded", + "Packet_Array_Field_VariableElementSize_ConstantSize", + "Packet_Array_Field_VariableElementSize_VariableSize", + "Packet_Array_Field_VariableElementSize_VariableCount", + "Packet_Array_Field_VariableElementSize_UnknownSize", + "Packet_Optional_Scalar_Field", + "Packet_Optional_Enum_Field", + "Packet_Optional_Struct_Field", + "Packet_Body_Field_UnknownSize", + "Packet_Body_Field_UnknownSize_Terminal", + "Packet_Body_Field_VariableSize", + "Packet_Count_Field", + "Packet_Enum8_Field", + "Packet_Enum_Field", + "Packet_FixedEnum_Field", + "Packet_FixedScalar_Field", + "Packet_Payload_Field_UnknownSize", + "Packet_Payload_Field_UnknownSize_Terminal", + "Packet_Payload_Field_VariableSize", + "Packet_Payload_Field_SizeModifier", + "Packet_Reserved_Field", + "Packet_Scalar_Field", + "Packet_Size_Field", + "Packet_Struct_Field", + "ScalarChild_A", + "ScalarChild_B", + "Struct_Count_Field", + "Struct_Array_Field_ByteElement_ConstantSize", + "Struct_Array_Field_ByteElement_UnknownSize", + "Struct_Array_Field_ByteElement_UnknownSize", + "Struct_Array_Field_ByteElement_VariableCount", + "Struct_Array_Field_ByteElement_VariableCount", + "Struct_Array_Field_ByteElement_VariableSize", + "Struct_Array_Field_ByteElement_VariableSize", + "Struct_Array_Field_EnumElement_ConstantSize", + "Struct_Array_Field_EnumElement_UnknownSize", + "Struct_Array_Field_EnumElement_UnknownSize", + "Struct_Array_Field_EnumElement_VariableCount", + "Struct_Array_Field_EnumElement_VariableCount", + "Struct_Array_Field_EnumElement_VariableSize", + "Struct_Array_Field_EnumElement_VariableSize", + "Struct_Array_Field_ScalarElement_ConstantSize", + "Struct_Array_Field_ScalarElement_UnknownSize", + "Struct_Array_Field_ScalarElement_UnknownSize", + "Struct_Array_Field_ScalarElement_VariableCount", + "Struct_Array_Field_ScalarElement_VariableCount", + "Struct_Array_Field_ScalarElement_VariableSize", + "Struct_Array_Field_ScalarElement_VariableSize", + "Struct_Array_Field_SizedElement_ConstantSize", + "Struct_Array_Field_SizedElement_UnknownSize", + "Struct_Array_Field_SizedElement_UnknownSize", + "Struct_Array_Field_SizedElement_VariableCount", + "Struct_Array_Field_SizedElement_VariableCount", + "Struct_Array_Field_SizedElement_VariableSize", + "Struct_Array_Field_SizedElement_VariableSize", + "Struct_Array_Field_UnsizedElement_ConstantSize", + "Struct_Array_Field_UnsizedElement_UnknownSize", + "Struct_Array_Field_UnsizedElement_UnknownSize", + "Struct_Array_Field_UnsizedElement_VariableCount", + "Struct_Array_Field_UnsizedElement_VariableCount", + "Struct_Array_Field_UnsizedElement_VariableSize", + "Struct_Array_Field_UnsizedElement_VariableSize", + "Struct_Array_Field_SizedElement_VariableSize_Padded", + "Struct_Array_Field_UnsizedElement_VariableCount_Padded", + "Struct_Optional_Scalar_Field", + "Struct_Optional_Enum_Field", + "Struct_Optional_Struct_Field", + "Struct_Enum_Field", + "Struct_FixedEnum_Field", + "Struct_FixedScalar_Field", + "Struct_Size_Field", + "Struct_Struct_Field", + "Enum_Incomplete_Truncated_Closed", + "Enum_Incomplete_Truncated_Open", + "Enum_Incomplete_Truncated_Closed_WithRange", + "Enum_Incomplete_Truncated_Open_WithRange", + "Enum_Complete_Truncated", + "Enum_Complete_Truncated_WithRange", + "Enum_Complete_WithRange", + ], + ) +} diff --git a/src/backends/rust/types.rs b/src/backends/rust/types.rs index 799cd4e..5c30d10 100644 --- a/src/backends/rust/types.rs +++ b/src/backends/rust/types.rs @@ -14,9 +14,8 @@ //! Utility functions for dealing with Rust integer types. -use crate::analyzer::ast as analyzer_ast; +use crate::ast; use crate::backends::rust::ToIdent; -use crate::{analyzer, ast}; use quote::{format_ident, quote}; /// A Rust integer type such as `u8`. @@ -49,7 +48,7 @@ impl quote::ToTokens for Integer { } } -pub fn rust_type(field: &analyzer_ast::Field) -> proc_macro2::TokenStream { +pub fn rust_type(field: &ast::Field) -> proc_macro2::TokenStream { match &field.desc { ast::FieldDesc::Scalar { width, .. } if field.cond.is_some() => { let field_type = Integer::new(*width); @@ -90,23 +89,6 @@ pub fn rust_type(field: &analyzer_ast::Field) -> proc_macro2::TokenStream { } } -pub fn rust_borrow( - field: &analyzer_ast::Field, - scope: &analyzer::Scope<'_>, -) -> proc_macro2::TokenStream { - match &field.desc { - ast::FieldDesc::Scalar { .. } => quote!(), - ast::FieldDesc::Typedef { type_id, .. } => match &scope.typedef[type_id].desc { - ast::DeclDesc::Enum { .. } => quote!(), - ast::DeclDesc::Struct { .. } => quote!(&), - ast::DeclDesc::CustomField { .. } => quote!(), - desc => unreachable!("unexpected declaration: {desc:?}"), - }, - ast::FieldDesc::Array { .. } => quote!(&), - _ => todo!(), - } -} - /// Suffix for `Buf::get_*` and `BufMut::put_*` methods when reading a /// value with the given `width`. fn endianness_suffix(endianness: ast::EndiannessValue, width: usize) -> &'static str { @@ -131,14 +113,14 @@ pub fn get_uint( if value_type.width == width { let get_u = format_ident!("get_u{}{}", value_type.width, suffix); quote! { - #span.get_mut().#get_u() + #span.#get_u() } } else { let get_uint = format_ident!("get_uint{}", suffix); let value_nbytes = proc_macro2::Literal::usize_unsuffixed(width / 8); let cast = (value_type.width < 64).then(|| quote!(as #value_type)); quote! { - #span.get_mut().#get_uint(#value_nbytes) #cast + #span.#get_uint(#value_nbytes) #cast } } } diff --git a/src/backends/rust.rs b/src/backends/rust_legacy/mod.rs index 6609482..5883487 100644 --- a/src/backends/rust.rs +++ b/src/backends/rust_legacy/mod.rs @@ -21,11 +21,10 @@ use std::collections::HashMap; use std::path::Path; use syn::LitInt; -use crate::analyzer::ast as analyzer_ast; - mod parser; mod preamble; mod serializer; +pub mod test; mod types; use parser::FieldParser; @@ -54,17 +53,6 @@ impl ToIdent for &'_ str { } } -/// Generate a block of code. -/// -/// Like `quote!`, but the code block will be followed by an empty -/// line of code. This makes the generated code more readable. -#[macro_export] -macro_rules! quote_block { - ($($tt:tt)*) => { - format!("{}\n\n", ::quote::quote!($($tt)*)) - } -} - /// Generate a bit-mask which masks out `n` least significant bits. /// /// Literal integers in Rust default to the `i32` type. For this @@ -86,14 +74,17 @@ pub fn mask_bits(n: usize, suffix: &str) -> syn::LitInt { fn generate_packet_size_getter<'a>( scope: &analyzer::Scope<'a>, - fields: impl Iterator<Item = &'a analyzer_ast::Field>, + schema: &analyzer::Schema, + fields: impl Iterator<Item = &'a ast::Field>, is_packet: bool, ) -> (usize, proc_macro2::TokenStream) { let mut constant_width = 0; let mut dynamic_widths = Vec::new(); for field in fields { - if let Some(width) = field.annot.static_() { + if let Some(width) = + schema.padded_size(field.key).or(schema.field_size(field.key).static_()) + { constant_width += width; continue; } @@ -142,7 +133,7 @@ fn generate_packet_size_getter<'a>( ast::FieldDesc::Array { id, width, .. } => { let id = id.to_ident(); match &decl { - Some(analyzer_ast::Decl { + Some(ast::Decl { desc: ast::DeclDesc::Struct { .. } | ast::DeclDesc::CustomField { .. }, .. }) => { @@ -150,9 +141,7 @@ fn generate_packet_size_getter<'a>( self.#id.iter().map(|elem| elem.get_size()).sum::<usize>() } } - Some(analyzer_ast::Decl { - desc: ast::DeclDesc::Enum { width, .. }, .. - }) => { + Some(ast::Decl { desc: ast::DeclDesc::Enum { width, .. }, .. }) => { let width = syn::Index::from(width / 8); let mul_width = (width.index > 1).then(|| quote!(* #width)); quote! { @@ -188,10 +177,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: &analyzer::Scope<'a>, packet_name: &'a str) -> &'a 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 @@ -209,8 +195,8 @@ fn top_level_packet<'a>( fn find_constrained_parent_fields<'a>( scope: &analyzer::Scope<'a>, id: &str, -) -> Vec<&'a analyzer_ast::Field> { - let all_parent_fields: HashMap<String, &'a analyzer_ast::Field> = HashMap::from_iter( +) -> Vec<&'a ast::Field> { + let all_parent_fields: HashMap<String, &'a ast::Field> = HashMap::from_iter( scope .iter_parent_fields(scope.typedef[id]) .filter_map(|f| f.id().map(|id| (id.to_string(), f))), @@ -244,6 +230,7 @@ fn find_constrained_parent_fields<'a>( /// how to parse and serialize its own fields. fn generate_data_struct( scope: &analyzer::Scope<'_>, + schema: &analyzer::Schema, endianness: ast::EndiannessValue, id: &str, ) -> (proc_macro2::TokenStream, proc_macro2::TokenStream) { @@ -252,8 +239,9 @@ fn generate_data_struct( 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); + let mut field_parser = FieldParser::new(scope, schema, endianness, id, &span); + let mut field_serializer = + FieldSerializer::new(scope, schema, endianness, id, &serializer_span); for field in decl.fields() { field_parser.add(field); field_serializer.add(field); @@ -270,7 +258,7 @@ fn generate_data_struct( }; let (constant_width, packet_size) = - generate_packet_size_getter(scope, decl.fields(), is_packet); + generate_packet_size_getter(scope, schema, decl.fields(), is_packet); let conforms = if constant_width == 0 { quote! { true } } else { @@ -319,7 +307,7 @@ fn generate_data_struct( #visibility fn parse( #span: &[u8] #(, #parse_arg_names: #parse_arg_types)* - ) -> Result<Self> { + ) -> Result<Self, DecodeError> { let mut cell = Cell::new(#span); let packet = Self::parse_inner(&mut cell #(, #parse_arg_names)*)?; // TODO(mgeisler): communicate back to user if !cell.get().is_empty()? @@ -328,15 +316,16 @@ fn generate_data_struct( fn parse_inner( mut #span: &mut Cell<&[u8]> #(, #parse_arg_names: #parse_arg_types)* - ) -> Result<Self> { + ) -> Result<Self, DecodeError> { #field_parser Ok(Self { #(#field_names,)* }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { #field_serializer + Ok(()) } fn get_total_size(&self) -> usize { @@ -355,7 +344,7 @@ fn generate_data_struct( /// Turn the constraint into a value (such as `10` or /// `SomeEnum::Foo`). pub fn constraint_to_value( - all_fields: &HashMap<String, &'_ analyzer_ast::Field>, + all_fields: &HashMap<String, &'_ ast::Field>, constraint: &ast::Constraint, ) -> proc_macro2::TokenStream { match constraint { @@ -380,6 +369,7 @@ pub fn constraint_to_value( /// Generate code for a `ast::Decl::Packet`. fn generate_packet_decl( scope: &analyzer::Scope<'_>, + schema: &analyzer::Schema, endianness: ast::EndiannessValue, id: &str, ) -> proc_macro2::TokenStream { @@ -587,15 +577,15 @@ fn generate_packet_decl( )* impl TryFrom<#top_level_packet> for #id_packet { - type Error = Error; - fn try_from(packet: #top_level_packet) -> Result<#id_packet> { + type Error = DecodeError; + fn try_from(packet: #top_level_packet) -> Result<#id_packet, Self::Error> { #id_packet::new(packet.#top_level_id_lower) } } } }); - let (data_struct_decl, data_struct_impl) = generate_data_struct(scope, endianness, id); + let (data_struct_decl, data_struct_impl) = generate_data_struct(scope, schema, endianness, id); quote! { #child_declaration @@ -621,51 +611,53 @@ fn generate_packet_decl( #data_struct_impl impl Packet for #id_packet { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.#top_level_id_lower.get_size()); - self.#top_level_id_lower.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() } - - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.#top_level_id_lower.write_to(buf) + } + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } - impl From<#id_packet> for Bytes { - fn from(packet: #id_packet) -> Self { - packet.to_bytes() + impl TryFrom<#id_packet> for Bytes { + type Error = EncodeError; + fn try_from(packet: #id_packet) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } - impl From<#id_packet> for Vec<u8> { - fn from(packet: #id_packet) -> Self { - packet.to_vec() + impl TryFrom<#id_packet> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: #id_packet) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } #impl_from_and_try_from impl #id_packet { - pub fn parse(#span: &[u8]) -> Result<Self> { + pub fn parse(#span: &[u8]) -> Result<Self, DecodeError> { let mut cell = Cell::new(#span); let packet = Self::parse_inner(&mut cell)?; // TODO(mgeisler): communicate back to user if !cell.get().is_empty()? Ok(packet) } - fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = #top_level_data::parse_inner(&mut bytes)?; Self::new(data) } #specialize - fn new(#top_level_id_lower: #top_level_data) -> Result<Self> { + fn new(#top_level_id_lower: #top_level_data) -> Result<Self, DecodeError> { #( let #parent_shifted_lower_ids = match &#parent_lower_ids.child { #parent_data_child::#parent_shifted_ids(value) => value.clone(), - _ => return Err(Error::InvalidChildError { + _ => return Err(DecodeError::InvalidChildError { expected: stringify!(#parent_data_child::#parent_shifted_ids), actual: format!("{:?}", &#parent_lower_ids.child), }), @@ -680,7 +672,7 @@ fn generate_packet_decl( #get_payload - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.#id_lower.write_to(buffer) } @@ -709,10 +701,11 @@ fn generate_packet_decl( /// Generate code for a `ast::Decl::Struct`. fn generate_struct_decl( scope: &analyzer::Scope<'_>, + schema: &analyzer::Schema, endianness: ast::EndiannessValue, id: &str, ) -> proc_macro2::TokenStream { - let (struct_decl, struct_impl) = generate_data_struct(scope, endianness, id); + let (struct_decl, struct_impl) = generate_data_struct(scope, schema, endianness, id); quote! { #struct_decl #struct_impl @@ -904,7 +897,7 @@ fn generate_enum_decl(id: &str, tags: &[ast::Tag], width: usize) -> proc_macro2: impl TryFrom<#backing_type> for #name { type Error = #backing_type; - fn try_from(value: #backing_type) -> std::result::Result<Self, Self::Error> { + fn try_from(value: #backing_type) -> Result<Self, Self::Error> { match value { #(#from_cases,)* } @@ -982,7 +975,7 @@ fn generate_custom_field_decl(id: &str, width: usize) -> proc_macro2::TokenStrea impl TryFrom<#backing_type> for #id { type Error = #backing_type; - fn try_from(value: #backing_type) -> std::result::Result<Self, Self::Error> { + fn try_from(value: #backing_type) -> Result<Self, Self::Error> { if value > #max_value { Err(value) } else { @@ -996,18 +989,21 @@ fn generate_custom_field_decl(id: &str, width: usize) -> proc_macro2::TokenStrea fn generate_decl( scope: &analyzer::Scope<'_>, - file: &analyzer_ast::File, - decl: &analyzer_ast::Decl, + schema: &analyzer::Schema, + file: &ast::File, + decl: &ast::Decl, ) -> proc_macro2::TokenStream { match &decl.desc { - ast::DeclDesc::Packet { id, .. } => generate_packet_decl(scope, file.endianness.value, id), + ast::DeclDesc::Packet { id, .. } => { + generate_packet_decl(scope, schema, file.endianness.value, id) + } ast::DeclDesc::Struct { id, parent_id: None, .. } => { // TODO(mgeisler): handle structs with parents. We could // generate code for them, but the code is not useful // since it would require the caller to unpack everything // manually. We either need to change the API, or // implement the recursive (de)serialization. - generate_struct_decl(scope, file.endianness.value, id) + generate_struct_decl(scope, schema, file.endianness.value, id) } ast::DeclDesc::Enum { id, tags, width } => generate_enum_decl(id, tags, *width), ast::DeclDesc::CustomField { id, width: Some(width), .. } => { @@ -1023,13 +1019,14 @@ fn generate_decl( /// readable source code. pub fn generate_tokens( sources: &ast::SourceDatabase, - file: &analyzer_ast::File, + file: &ast::File, ) -> proc_macro2::TokenStream { 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 decls = file.declarations.iter().map(|decl| generate_decl(&scope, file, decl)); + let schema = analyzer::Schema::new(file); + let decls = file.declarations.iter().map(|decl| generate_decl(&scope, &schema, file, decl)); quote! { #preamble @@ -1041,7 +1038,7 @@ pub fn generate_tokens( /// /// The code is not formatted, pipe it through `rustfmt` to get /// readable source code. -pub fn generate(sources: &ast::SourceDatabase, file: &analyzer_ast::File) -> String { +pub fn generate(sources: &ast::SourceDatabase, file: &ast::File) -> String { let syntax_tree = syn::parse2(generate_tokens(sources, file)).expect("Could not parse code"); prettyplease::unparse(&syntax_tree) } @@ -1061,7 +1058,7 @@ mod tests { /// # Panics /// /// Panics on parse errors. - pub fn parse_str(text: &str) -> analyzer_ast::File { + pub fn parse_str(text: &str) -> ast::File { let mut db = ast::SourceDatabase::new(); let file = parse_inline(&mut db, "stdin", String::from(text)).expect("parse error"); analyzer::analyze(&file).expect("analyzer error") @@ -1132,7 +1129,7 @@ mod tests { let file = analyzer::analyze(&file).unwrap(); let actual_code = generate(&db, &file); assert_snapshot_eq( - &format!("tests/generated/{name}_{endianness}.rs"), + &format!("tests/generated/rust_legacy/{name}_{endianness}.rs"), &format_rust(&actual_code), ); } diff --git a/src/backends/rust_legacy/parser.rs b/src/backends/rust_legacy/parser.rs new file mode 100644 index 0000000..0558411 --- /dev/null +++ b/src/backends/rust_legacy/parser.rs @@ -0,0 +1,861 @@ +// 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 crate::backends::rust_legacy::{ + constraint_to_value, find_constrained_parent_fields, mask_bits, types, ToIdent, + ToUpperCamelCase, +}; +use crate::{analyzer, ast}; +use quote::{format_ident, quote}; +use std::collections::{BTreeSet, HashMap}; + +fn size_field_ident(id: &str) -> proc_macro2::Ident { + format_ident!("{}_size", id.trim_matches('_')) +} + +/// A single bit-field. +struct BitField<'a> { + shift: usize, // The shift to apply to this field. + field: &'a ast::Field, +} + +pub struct FieldParser<'a> { + scope: &'a analyzer::Scope<'a>, + schema: &'a analyzer::Schema, + endianness: ast::EndiannessValue, + decl: &'a ast::Decl, + packet_name: &'a str, + span: &'a proc_macro2::Ident, + chunk: Vec<BitField<'a>>, + code: Vec<proc_macro2::TokenStream>, + shift: usize, + offset: usize, +} + +impl<'a> FieldParser<'a> { + pub fn new( + scope: &'a analyzer::Scope<'a>, + schema: &'a analyzer::Schema, + endianness: ast::EndiannessValue, + packet_name: &'a str, + span: &'a proc_macro2::Ident, + ) -> FieldParser<'a> { + FieldParser { + scope, + schema, + endianness, + decl: scope.typedef[packet_name], + packet_name, + span, + chunk: Vec::new(), + code: Vec::new(), + shift: 0, + offset: 0, + } + } + + pub fn add(&mut self, field: &'a ast::Field) { + match &field.desc { + _ if field.cond.is_some() => self.add_optional_field(field), + _ if self.scope.is_bitfield(field) => self.add_bit_field(field), + ast::FieldDesc::Padding { .. } => (), + ast::FieldDesc::Array { id, width, type_id, size, .. } => self.add_array_field( + id, + *width, + type_id.as_deref(), + *size, + self.schema.padded_size(field.key), + self.scope.get_type_declaration(field), + ), + ast::FieldDesc::Typedef { id, type_id } => self.add_typedef_field(id, type_id), + ast::FieldDesc::Payload { size_modifier, .. } => { + self.add_payload_field(size_modifier.as_deref()) + } + ast::FieldDesc::Body { .. } => self.add_payload_field(None), + _ => todo!("{field:?}"), + } + } + + fn add_optional_field(&mut self, field: &'a ast::Field) { + let cond_id = field.cond.as_ref().unwrap().id.to_ident(); + let cond_value = syn::parse_str::<syn::LitInt>(&format!( + "{}", + field.cond.as_ref().unwrap().value.unwrap() + )) + .unwrap(); + + self.code.push(match &field.desc { + ast::FieldDesc::Scalar { id, width } => { + let id = id.to_ident(); + let value = types::get_uint(self.endianness, *width, self.span); + quote! { + let #id = (#cond_id == #cond_value).then(|| #value); + } + } + ast::FieldDesc::Typedef { id, type_id } => match &self.scope.typedef[type_id].desc { + ast::DeclDesc::Enum { width, .. } => { + let name = id; + let type_name = type_id; + let id = id.to_ident(); + let type_id = type_id.to_ident(); + let decl_id = &self.packet_name; + let value = types::get_uint(self.endianness, *width, self.span); + quote! { + let #id = (#cond_id == #cond_value) + .then(|| + #type_id::try_from(#value).map_err(|unknown_val| { + DecodeError::InvalidEnumValueError { + obj: #decl_id, + field: #name, + value: unknown_val as u64, + type_: #type_name, + } + })) + .transpose()?; + } + } + ast::DeclDesc::Struct { .. } => { + let id = id.to_ident(); + let type_id = type_id.to_ident(); + let span = self.span; + quote! { + let #id = (#cond_id == #cond_value) + .then(|| #type_id::parse_inner(&mut #span)) + .transpose()?; + } + } + _ => unreachable!(), + }, + _ => unreachable!(), + }) + } + + fn add_bit_field(&mut self, field: &'a ast::Field) { + self.chunk.push(BitField { shift: self.shift, field }); + self.shift += self.schema.field_size(field.key).static_().unwrap(); + if self.shift % 8 != 0 { + return; + } + + let size = self.shift / 8; + let end_offset = self.offset + size; + + let wanted = proc_macro2::Literal::usize_unsuffixed(size); + self.check_size(self.span, "e!(#wanted)); + + let chunk_type = types::Integer::new(self.shift); + // TODO(mgeisler): generate Rust variable names which cannot + // conflict with PDL field names. An option would be to start + // Rust variable names with `_`, but that has a special + // semantic in Rust. + let chunk_name = format_ident!("chunk"); + + let get = types::get_uint(self.endianness, self.shift, self.span); + if self.chunk.len() > 1 { + // Multiple values: we read into a local variable. + self.code.push(quote! { + let #chunk_name = #get; + }); + } + + let single_value = self.chunk.len() == 1; // && self.chunk[0].offset == 0; + for BitField { shift, field } in self.chunk.drain(..) { + let mut v = if single_value { + // Single value: read directly. + quote! { #get } + } else { + // Multiple values: read from `chunk_name`. + quote! { #chunk_name } + }; + + if shift > 0 { + let shift = proc_macro2::Literal::usize_unsuffixed(shift); + v = quote! { (#v >> #shift) } + } + + let width = self.schema.field_size(field.key).static_().unwrap(); + let value_type = types::Integer::new(width); + if !single_value && width < value_type.width { + // Mask value if we grabbed more than `width` and if + // `as #value_type` doesn't already do the masking. + let mask = mask_bits(width, "u64"); + v = quote! { (#v & #mask) }; + } + + if value_type.width < chunk_type.width { + v = quote! { #v as #value_type }; + } + + self.code.push(match &field.desc { + ast::FieldDesc::Scalar { id, .. } + | ast::FieldDesc::Flag { id, .. } => { + let id = id.to_ident(); + 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(); + quote! { + let fixed_value = #v; + if fixed_value != #value_type::from(#enum_id::#tag_id) { + return Err(DecodeError::InvalidFixedValue { + expected: #value_type::from(#enum_id::#tag_id) as u64, + actual: fixed_value as u64, + }); + } + } + } + ast::FieldDesc::FixedScalar { value, .. } => { + let value = proc_macro2::Literal::usize_unsuffixed(*value); + quote! { + let fixed_value = #v; + if fixed_value != #value { + return Err(DecodeError::InvalidFixedValue { + expected: #value, + actual: fixed_value as u64, + }); + } + } + } + ast::FieldDesc::Typedef { id, type_id } => { + 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(); + quote! { + let #id = #type_id::try_from(#v).map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: #packet_name, + field: #field_name, + value: unknown_val as u64, + type_: #type_name, + })?; + } + } + ast::FieldDesc::Reserved { .. } => { + if single_value { + let span = self.span; + let size = proc_macro2::Literal::usize_unsuffixed(size); + quote! { + #span.get_mut().advance(#size); + } + } else { + // Otherwise we don't need anything: we will + // have advanced past the reserved field when + // reading the chunk above. + quote! {} + } + } + ast::FieldDesc::Size { field_id, .. } => { + let id = size_field_ident(field_id); + quote! { + let #id = #v as usize; + } + } + ast::FieldDesc::Count { field_id, .. } => { + let id = format_ident!("{field_id}_count"); + quote! { + let #id = #v as usize; + } + } + _ => todo!(), + }); + } + + self.offset = end_offset; + self.shift = 0; + } + + fn find_count_field(&self, id: &str) -> Option<proc_macro2::Ident> { + match self.decl.array_size(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 { + 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(); + fields.find(|f| { + matches!(f.desc, ast::FieldDesc::Body { .. } | ast::FieldDesc::Payload { .. }) + })?; + + let mut offset = 0; + for field in fields { + if let Some(width) = + self.schema.padded_size(field.key).or(self.schema.field_size(field.key).static_()) + { + offset += width; + } else { + return None; + } + } + + Some(offset) + } + + fn check_size(&mut self, span: &proc_macro2::Ident, wanted: &proc_macro2::TokenStream) { + let packet_name = &self.packet_name; + self.code.push(quote! { + if #span.get().remaining() < #wanted { + return Err(DecodeError::InvalidLengthError { + obj: #packet_name, + wanted: #wanted, + got: #span.get().remaining(), + }); + } + }); + } + + fn add_array_field( + &mut self, + id: &str, + // `width`: the width in bits of the array elements (if Some). + width: Option<usize>, + // `type_id`: the enum type of the array elements (if Some). + // Mutually exclusive with `width`. + type_id: Option<&str>, + // `size`: the size of the array in number of elements (if + // known). If None, the array is a Vec with a dynamic size. + size: Option<usize>, + padding_size: Option<usize>, + decl: Option<&ast::Decl>, + ) { + enum ElementWidth { + Static(usize), // Static size in bytes. + Unknown, + } + let element_width = + match width.or_else(|| self.schema.total_size(decl.unwrap().key).static_()) { + Some(w) => { + assert_eq!(w % 8, 0, "Array element size ({w}) is not a multiple of 8"); + ElementWidth::Static(w / 8) + } + None => ElementWidth::Unknown, + }; + + // The "shape" of the array, i.e., the number of elements + // given via a static count, a count field, a size field, or + // unknown. + enum ArrayShape { + Static(usize), // Static count + CountField(proc_macro2::Ident), // Count based on count field + SizeField(proc_macro2::Ident), // Count based on size and field + Unknown, // Variable count based on remaining bytes + } + let array_shape = if let Some(count) = size { + ArrayShape::Static(count) + } else if let Some(count_field) = self.find_count_field(id) { + ArrayShape::CountField(count_field) + } else if let Some(size_field) = self.find_size_field(id) { + ArrayShape::SizeField(size_field) + } else { + ArrayShape::Unknown + }; + + // TODO size modifier + + let span = match padding_size { + Some(padding_size) => { + let span = self.span; + let padding_octets = padding_size / 8; + self.check_size(span, "e!(#padding_octets)); + self.code.push(quote! { + let (head, tail) = #span.get().split_at(#padding_octets); + let mut head = &mut Cell::new(head); + #span.replace(tail); + }); + format_ident!("head") + } + None => self.span.clone(), + }; + + let id = id.to_ident(); + + let parse_element = self.parse_array_element(&span, width, type_id, decl); + match (element_width, &array_shape) { + (ElementWidth::Unknown, ArrayShape::SizeField(size_field)) => { + // The element width is not known, but the array full + // octet size is known by size field. Parse elements + // item by item as a vector. + self.check_size(&span, "e!(#size_field)); + let parse_element = + self.parse_array_element(&format_ident!("head"), width, type_id, decl); + self.code.push(quote! { + let (head, tail) = #span.get().split_at(#size_field); + let mut head = &mut Cell::new(head); + #span.replace(tail); + let mut #id = Vec::new(); + while !head.get().is_empty() { + #id.push(#parse_element?); + } + }); + } + (ElementWidth::Unknown, ArrayShape::Static(count)) => { + // The element width is not known, but the array + // element count is known statically. Parse elements + // item by item as an array. + let count = syn::Index::from(*count); + self.code.push(quote! { + // TODO(mgeisler): use + // https://doc.rust-lang.org/std/array/fn.try_from_fn.html + // when stabilized. + let #id = (0..#count) + .map(|_| #parse_element) + .collect::<Result<Vec<_>, DecodeError>>()? + .try_into() + .map_err(|_| DecodeError::InvalidPacketError)?; + }); + } + (ElementWidth::Unknown, ArrayShape::CountField(count_field)) => { + // The element width is not known, but the array + // element count is known by the count field. Parse + // elements item by item as a vector. + self.code.push(quote! { + let #id = (0..#count_field) + .map(|_| #parse_element) + .collect::<Result<Vec<_>, DecodeError>>()?; + }); + } + (ElementWidth::Unknown, ArrayShape::Unknown) => { + // Neither the count not size is known, parse elements + // until the end of the span. + self.code.push(quote! { + let mut #id = Vec::new(); + while !#span.get().is_empty() { + #id.push(#parse_element?); + } + }); + } + (ElementWidth::Static(element_width), ArrayShape::Static(count)) => { + // The element width is known, and the array element + // count is known statically. + let count = syn::Index::from(*count); + // This creates a nicely formatted size. + let array_size = if element_width == 1 { + quote!(#count) + } else { + let element_width = syn::Index::from(element_width); + quote!(#count * #element_width) + }; + self.check_size(&span, "e! { #array_size }); + self.code.push(quote! { + // TODO(mgeisler): use + // https://doc.rust-lang.org/std/array/fn.try_from_fn.html + // when stabilized. + let #id = (0..#count) + .map(|_| #parse_element) + .collect::<Result<Vec<_>, DecodeError>>()? + .try_into() + .map_err(|_| DecodeError::InvalidPacketError)?; + }); + } + (ElementWidth::Static(element_width), ArrayShape::CountField(count_field)) => { + // The element width is known, and the array element + // count is known dynamically by the count field. + self.check_size(&span, "e!(#count_field * #element_width)); + self.code.push(quote! { + let #id = (0..#count_field) + .map(|_| #parse_element) + .collect::<Result<Vec<_>, DecodeError>>()?; + }); + } + (ElementWidth::Static(element_width), ArrayShape::SizeField(_)) + | (ElementWidth::Static(element_width), ArrayShape::Unknown) => { + // The element width is known, and the array full size + // is known by size field, or unknown (in which case + // it is the remaining span length). + let array_size = if let ArrayShape::SizeField(size_field) = &array_shape { + self.check_size(&span, "e!(#size_field)); + quote!(#size_field) + } else { + quote!(#span.get().remaining()) + }; + let count_field = format_ident!("{id}_count"); + let array_count = if element_width != 1 { + let element_width = syn::Index::from(element_width); + self.code.push(quote! { + if #array_size % #element_width != 0 { + return Err(DecodeError::InvalidArraySize { + array: #array_size, + element: #element_width, + }); + } + let #count_field = #array_size / #element_width; + }); + quote!(#count_field) + } else { + array_size + }; + + self.code.push(quote! { + let mut #id = Vec::with_capacity(#array_count); + for _ in 0..#array_count { + #id.push(#parse_element?); + } + }); + } + } + } + + /// Parse typedef fields. + /// + /// This is only for non-enum fields: enums are parsed via + /// add_bit_field. + fn add_typedef_field(&mut self, id: &str, type_id: &str) { + assert_eq!(self.shift, 0, "Typedef field does not start on an octet boundary"); + + let decl = self.scope.typedef[type_id]; + if let ast::DeclDesc::Struct { parent_id: Some(_), .. } = &decl.desc { + panic!("Derived struct used in typedef field"); + } + + let span = self.span; + let id = id.to_ident(); + let type_id = type_id.to_ident(); + + self.code.push(match self.schema.decl_size(decl.key) { + analyzer::Size::Unknown | analyzer::Size::Dynamic => quote! { + let #id = #type_id::parse_inner(&mut #span)?; + }, + analyzer::Size::Static(width) => { + assert_eq!(width % 8, 0, "Typedef field type size is not a multiple of 8"); + match &decl.desc { + ast::DeclDesc::Checksum { .. } => todo!(), + ast::DeclDesc::CustomField { .. } if [8, 16, 32, 64].contains(&width) => { + let get_uint = types::get_uint(self.endianness, width, span); + quote! { + let #id = #get_uint.into(); + } + } + ast::DeclDesc::CustomField { .. } => { + let get_uint = types::get_uint(self.endianness, width, span); + quote! { + let #id = (#get_uint) + .try_into() + .unwrap(); // Value is masked and conversion must succeed. + } + } + ast::DeclDesc::Struct { .. } => { + let width = syn::Index::from(width / 8); + quote! { + let (head, tail) = #span.get().split_at(#width); + #span.replace(tail); + let #id = #type_id::parse(head)?; + } + } + _ => unreachable!(), + } + } + }); + } + + /// 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 offset_from_end = self.payload_field_offset_from_end(); + + if self.shift != 0 { + todo!("Unexpected non byte aligned payload"); + } + + if let Some(ast::FieldDesc::Size { field_id, .. }) = &payload_size_field.map(|f| &f.desc) { + // The payload or body has a known size. Consume the + // payload and update the span in case fields are placed + // after the payload. + let size_field = size_field_ident(field_id); + if let Some(size_modifier) = size_modifier { + let size_modifier = proc_macro2::Literal::usize_unsuffixed( + size_modifier.parse::<usize>().expect("failed to parse the size modifier"), + ); + let packet_name = &self.packet_name; + // Push code to check that the size is greater than the size + // modifier. Required to safely substract the modifier from the + // size. + self.code.push(quote! { + if #size_field < #size_modifier { + return Err(DecodeError::InvalidLengthError { + obj: #packet_name, + wanted: #size_modifier, + got: #size_field, + }); + } + let #size_field = #size_field - #size_modifier; + }); + } + self.check_size(self.span, "e!(#size_field )); + self.code.push(quote! { + let payload = &#span.get()[..#size_field]; + #span.get_mut().advance(#size_field); + }); + } else if offset_from_end == Some(0) { + // The payload or body is the last field of a packet, + // consume the remaining span. + self.code.push(quote! { + let payload = #span.get(); + #span.get_mut().advance(payload.len()); + }); + } else if let Some(offset_from_end) = offset_from_end { + // The payload or body is followed by fields of static + // size. Consume the span that is not reserved for the + // following fields. + assert_eq!( + offset_from_end % 8, + 0, + "Payload field offset from end of packet is not a multiple of 8" + ); + let offset_from_end = syn::Index::from(offset_from_end / 8); + self.check_size(self.span, "e!(#offset_from_end)); + self.code.push(quote! { + let payload = &#span.get()[..#span.get().len() - #offset_from_end]; + #span.get_mut().advance(payload.len()); + }); + } + + let decl = self.scope.typedef[self.packet_name]; + if let ast::DeclDesc::Struct { .. } = &decl.desc { + self.code.push(quote! { + let payload = Vec::from(payload); + }); + } + } + + /// Parse a single array field element from `span`. + fn parse_array_element( + &self, + span: &proc_macro2::Ident, + width: Option<usize>, + type_id: Option<&str>, + decl: Option<&ast::Decl>, + ) -> proc_macro2::TokenStream { + if let Some(width) = width { + let get_uint = types::get_uint(self.endianness, width, span); + return quote! { + Ok::<_, DecodeError>(#get_uint) + }; + } + + 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 packet_name = &self.packet_name; + return quote! { + #type_id::try_from(#get_uint).map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: #packet_name, + field: "", // TODO(mgeisler): fill out or remove + value: unknown_val as u64, + type_: #id, + }) + }; + } + + let type_id = type_id.unwrap().to_ident(); + quote! { + #type_id::parse_inner(#span) + } + } + + pub fn done(&mut self) { + let decl = self.scope.typedef[self.packet_name]; + if let ast::DeclDesc::Struct { .. } = &decl.desc { + 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() { + 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. + let constrained_fields = children + .iter() + .flat_map(|child| child.constraints().map(|c| &c.id)) + .collect::<BTreeSet<_>>(); + + let mut match_values = Vec::new(); + 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)) + }; + + for child in children.iter() { + let tuple_values = constrained_fields + .iter() + .map(|id| { + get_constraint_value(child.constraints(), id).map(|v| vec![v]).unwrap_or_else( + || { + self.scope + .file + .iter_children(child) + .filter_map(|d| get_constraint_value(d.constraints(), id)) + .collect() + }, + ) + }) + .collect::<Vec<_>>(); + + // If no constraint values are found for the tuple just skip the child + // packet as it would capture unwanted input packets. + if tuple_values.iter().all(|v| v.is_empty()) { + continue; + } + + let tuple_values = tuple_values + .iter() + .map(|v| v.is_empty().then_some(quote!(_)).unwrap_or_else(|| quote!( #(#v)|* ))) + .collect::<Vec<_>>(); + + let fields = find_constrained_parent_fields(self.scope, child.id().unwrap()) + .iter() + .map(|field| field.id().unwrap().to_ident()) + .collect::<Vec<_>>(); + + 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()); + } + + let constrained_field_idents = constrained_fields.iter().map(|field| field.to_ident()); + let packet_data_child = format_ident!("{}DataChild", self.packet_name); + + // Parsing of packet children requires having a payload field; + // it is allowed to inherit from a packet with empty payload, in this + // case generate an empty payload value. + if !decl + .fields() + .any(|f| matches!(&f.desc, ast::FieldDesc::Payload { .. } | ast::FieldDesc::Body)) + { + self.code.push(quote! { + let payload: &[u8] = &[]; + }) + } + self.code.push(quote! { + let child = match (#(#constrained_field_idents),*) { + #(#match_values if #child_ids_data::conforms(&payload) => { + let mut cell = Cell::new(payload); + let child_data = #child_ids_data::parse_inner(&mut cell #child_parse_args)?; + // TODO(mgeisler): communicate back to user if !cell.get().is_empty()? + #packet_data_child::#child_ids(child_data) + }),* + _ if !payload.is_empty() => { + #packet_data_child::Payload(Bytes::copy_from_slice(payload)) + } + _ => #packet_data_child::None, + }; + }); + } +} + +impl quote::ToTokens for FieldParser<'_> { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let code = &self.code; + tokens.extend(quote! { + #(#code)* + }); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::analyzer; + use crate::ast; + use crate::parser::parse_inline; + + /// Parse a string fragment as a PDL file. + /// + /// # Panics + /// + /// Panics on parse errors. + pub fn parse_str(text: &str) -> ast::File { + let mut db = ast::SourceDatabase::new(); + let file = parse_inline(&mut db, "stdin", String::from(text)).expect("parse error"); + analyzer::analyze(&file).expect("analyzer error") + } + + #[test] + fn test_find_fields_static() { + let code = " + little_endian_packets + packet P { + a: 24[3], + } + "; + let file = parse_str(code); + let scope = analyzer::Scope::new(&file).unwrap(); + let schema = analyzer::Schema::new(&file); + let span = format_ident!("bytes"); + let parser = FieldParser::new(&scope, &schema, file.endianness.value, "P", &span); + assert_eq!(parser.find_size_field("a"), None); + assert_eq!(parser.find_count_field("a"), None); + } + + #[test] + fn test_find_fields_dynamic_count() { + let code = " + little_endian_packets + packet P { + _count_(b): 24, + b: 16[], + } + "; + let file = parse_str(code); + let scope = analyzer::Scope::new(&file).unwrap(); + let schema = analyzer::Schema::new(&file); + let span = format_ident!("bytes"); + let parser = FieldParser::new(&scope, &schema, file.endianness.value, "P", &span); + assert_eq!(parser.find_size_field("b"), None); + assert_eq!(parser.find_count_field("b"), Some(format_ident!("b_count"))); + } + + #[test] + fn test_find_fields_dynamic_size() { + let code = " + little_endian_packets + packet P { + _size_(c): 8, + c: 24[], + } + "; + let file = parse_str(code); + let scope = analyzer::Scope::new(&file).unwrap(); + let schema = analyzer::Schema::new(&file); + let span = format_ident!("bytes"); + let parser = FieldParser::new(&scope, &schema, file.endianness.value, "P", &span); + assert_eq!(parser.find_size_field("c"), Some(format_ident!("c_size"))); + assert_eq!(parser.find_count_field("c"), None); + } +} diff --git a/src/backends/rust_legacy/preamble.rs b/src/backends/rust_legacy/preamble.rs new file mode 100644 index 0000000..b2647bb --- /dev/null +++ b/src/backends/rust_legacy/preamble.rs @@ -0,0 +1,93 @@ +// 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 quote::quote; +use std::path::Path; + +/// Generate the file preamble. +pub fn generate(path: &Path) -> proc_macro2::TokenStream { + // TODO(mgeisler): Make the generated code free from warnings. + // + // The code either needs + // + // clippy_lints: "none", + // lints: "none", + // + // in the Android.bp file, or we need to add + // + // #![allow(warnings, missing_docs)] + // + // to the generated code. We cannot add the module-level attribute + // here because of how the generated code is used with include! in + // lmp/src/packets.rs. + let filename = path.file_name().unwrap().to_str().expect("non UTF-8 filename"); + let module_doc_string = format!(" @generated rust packets from {filename}."); + // TODO(mgeisler): the doc comment below should be an outer + // comment (#![doc = ...]). However, people include the generated + // code in the middle of another module via include_str!: + // + // fn before() {} + // include_str!("generated.rs") + // fn after() {} + // + // It is illegal to have a //! comment in the middle of a file. We + // should refactor such usages to instead look like this: + // + // fn before() {} + // mod foo { include_str!("generated.rs") } + // use foo::*; + // fn after() {} + quote! { + #[doc = #module_doc_string] + + use bytes::{Buf, BufMut, Bytes, BytesMut}; + use std::convert::{TryFrom, TryInto}; + use std::cell::Cell; + use std::fmt; + use std::result::Result; + use pdl_runtime::{DecodeError, EncodeError, Packet}; + + /// 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(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 + } + } + + impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test_utils::{assert_snapshot_eq, format_rust}; + + #[test] + fn test_generate_preamble() { + let actual_code = generate(Path::new("some/path/foo.pdl")).to_string(); + assert_snapshot_eq("tests/generated/rust_legacy/preamble.rs", &format_rust(&actual_code)); + } +} diff --git a/src/backends/rust_legacy/serializer.rs b/src/backends/rust_legacy/serializer.rs new file mode 100644 index 0000000..2262d27 --- /dev/null +++ b/src/backends/rust_legacy/serializer.rs @@ -0,0 +1,519 @@ +// 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 crate::backends::rust_legacy::{mask_bits, types, ToIdent, ToUpperCamelCase}; +use crate::{analyzer, ast}; +use quote::{format_ident, quote}; + +/// A single bit-field value. +struct BitField { + value: proc_macro2::TokenStream, // An expression which produces a value. + field_type: types::Integer, // The type of the value. + shift: usize, // A bit-shift to apply to `value`. +} + +pub struct FieldSerializer<'a> { + scope: &'a analyzer::Scope<'a>, + schema: &'a analyzer::Schema, + endianness: ast::EndiannessValue, + packet_name: &'a str, + span: &'a proc_macro2::Ident, + chunk: Vec<BitField>, + code: Vec<proc_macro2::TokenStream>, + shift: usize, +} + +impl<'a> FieldSerializer<'a> { + pub fn new( + scope: &'a analyzer::Scope<'a>, + schema: &'a analyzer::Schema, + endianness: ast::EndiannessValue, + packet_name: &'a str, + span: &'a proc_macro2::Ident, + ) -> FieldSerializer<'a> { + FieldSerializer { + scope, + schema, + endianness, + packet_name, + span, + chunk: Vec::new(), + code: Vec::new(), + shift: 0, + } + } + + pub fn add(&mut self, field: &ast::Field) { + match &field.desc { + _ if field.cond.is_some() => self.add_optional_field(field), + _ if self.scope.is_bitfield(field) => self.add_bit_field(field), + ast::FieldDesc::Array { id, width, .. } => self.add_array_field( + id, + *width, + self.schema.padded_size(field.key), + self.scope.get_type_declaration(field), + ), + ast::FieldDesc::Typedef { id, type_id } => { + self.add_typedef_field(id, type_id); + } + ast::FieldDesc::Payload { .. } | ast::FieldDesc::Body { .. } => { + self.add_payload_field(); + } + // Padding field handled in serialization of associated array field. + ast::FieldDesc::Padding { .. } => (), + _ => todo!("Cannot yet serialize {field:?}"), + } + } + + fn add_optional_field(&mut self, field: &ast::Field) { + self.code.push(match &field.desc { + ast::FieldDesc::Scalar { id, width } => { + let name = id; + let id = id.to_ident(); + let backing_type = types::Integer::new(*width); + let write = types::put_uint(self.endianness, "e!(*#id), *width, self.span); + + let range_check = (backing_type.width > *width).then(|| { + let packet_name = &self.packet_name; + let max_value = mask_bits(*width, "u64"); + + quote! { + if *#id > #max_value { + return Err(EncodeError::InvalidScalarValue { + packet: #packet_name, + field: #name, + value: *#id as u64, + maximum_value: #max_value as u64, + }) + } + } + }); + + quote! { + if let Some(#id) = &self.#id { + #range_check + #write + } + } + } + ast::FieldDesc::Typedef { id, type_id } => match &self.scope.typedef[type_id].desc { + ast::DeclDesc::Enum { width, .. } => { + let id = id.to_ident(); + let backing_type = types::Integer::new(*width); + let write = types::put_uint( + self.endianness, + "e!(#backing_type::from(#id)), + *width, + self.span, + ); + quote! { + if let Some(#id) = &self.#id { + #write + } + } + } + ast::DeclDesc::Struct { .. } => { + let id = id.to_ident(); + let span = self.span; + quote! { + if let Some(#id) = &self.#id { + #id.write_to(#span)?; + } + } + } + _ => unreachable!(), + }, + _ => unreachable!(), + }) + } + + fn add_bit_field(&mut self, field: &ast::Field) { + let width = self.schema.field_size(field.key).static_().unwrap(); + let shift = self.shift; + + match &field.desc { + ast::FieldDesc::Flag { optional_field_id, set_value, .. } => { + let optional_field_id = optional_field_id.to_ident(); + let cond_value_present = + syn::parse_str::<syn::LitInt>(&format!("{}", set_value)).unwrap(); + let cond_value_absent = + syn::parse_str::<syn::LitInt>(&format!("{}", 1 - set_value)).unwrap(); + self.chunk.push(BitField { + value: quote! { + if self.#optional_field_id.is_some() { + #cond_value_present + } else { + #cond_value_absent + } + }, + field_type: types::Integer::new(1), + shift, + }); + } + ast::FieldDesc::Scalar { id, width } => { + let field_name = id.to_ident(); + let field_type = types::Integer::new(*width); + if field_type.width > *width { + let packet_name = &self.packet_name; + let max_value = mask_bits(*width, "u64"); + self.code.push(quote! { + if self.#field_name > #max_value { + return Err(EncodeError::InvalidScalarValue { + packet: #packet_name, + field: #id, + value: self.#field_name as u64, + maximum_value: #max_value, + }) + } + }); + } + self.chunk.push(BitField { value: quote!(self.#field_name), field_type, shift }); + } + ast::FieldDesc::FixedEnum { enum_id, tag_id, .. } => { + let field_type = types::Integer::new(width); + let enum_id = enum_id.to_ident(); + let tag_id = format_ident!("{}", tag_id.to_upper_camel_case()); + self.chunk.push(BitField { + value: quote!(#field_type::from(#enum_id::#tag_id)), + field_type, + shift, + }); + } + ast::FieldDesc::FixedScalar { value, .. } => { + let field_type = types::Integer::new(width); + let value = proc_macro2::Literal::usize_unsuffixed(*value); + self.chunk.push(BitField { value: quote!(#value), field_type, shift }); + } + ast::FieldDesc::Typedef { id, .. } => { + let field_name = id.to_ident(); + let field_type = types::Integer::new(width); + self.chunk.push(BitField { + value: quote!(#field_type::from(self.#field_name)), + field_type, + shift, + }); + } + ast::FieldDesc::Reserved { .. } => { + // Nothing to do here. + } + ast::FieldDesc::Size { field_id, width, .. } => { + let packet_name = &self.packet_name; + 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 field_name = field_id.to_ident(); + let field_type = types::Integer::new(*width); + // TODO: size modifier + + let value_field_decl = self.scope.get_type_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)) + { + (ast::FieldDesc::Payload { size_modifier: Some(size_modifier) }, _) => { + let size_modifier = proc_macro2::Literal::usize_unsuffixed( + size_modifier + .parse::<usize>() + .expect("failed to parse the size modifier"), + ); + if let ast::DeclDesc::Packet { .. } = &decl.desc { + quote! { (self.child.get_total_size() + #size_modifier) } + } else { + quote! { (self.payload.len() + #size_modifier) } + } + } + (ast::FieldDesc::Payload { .. } | ast::FieldDesc::Body { .. }, _) => { + if let ast::DeclDesc::Packet { .. } = &decl.desc { + quote! { self.child.get_total_size() } + } else { + quote! { self.payload.len() } + } + } + (ast::FieldDesc::Array { width: Some(width), .. }, _) + | (ast::FieldDesc::Array { .. }, Some(ast::DeclDesc::Enum { width, .. })) => { + let byte_width = syn::Index::from(width / 8); + if byte_width.index == 1 { + quote! { self.#field_name.len() } + } else { + quote! { (self.#field_name.len() * #byte_width) } + } + } + (ast::FieldDesc::Array { .. }, _) => { + self.code.push(quote! { + let #field_size_name = self.#field_name + .iter() + .map(|elem| elem.get_size()) + .sum::<usize>(); + }); + quote! { #field_size_name } + } + _ => panic!("Unexpected size field: {field:?}"), + }; + + self.code.push(quote! { + if #array_size > #max_value { + return Err(EncodeError::SizeOverflow { + packet: #packet_name, + field: #field_id, + size: #array_size, + maximum_size: #max_value, + }) + } + }); + + self.chunk.push(BitField { + value: quote!(#array_size as #field_type), + field_type, + shift, + }); + } + ast::FieldDesc::Count { field_id, width, .. } => { + let field_name = field_id.to_ident(); + let field_type = types::Integer::new(*width); + if field_type.width > *width { + let packet_name = &self.packet_name; + let max_value = mask_bits(*width, "usize"); + self.code.push(quote! { + if self.#field_name.len() > #max_value { + return Err(EncodeError::CountOverflow { + packet: #packet_name, + field: #field_id, + count: self.#field_name.len(), + maximum_count: #max_value, + }) + } + }); + } + self.chunk.push(BitField { + value: quote!(self.#field_name.len() as #field_type), + field_type, + shift, + }); + } + _ => todo!("{field:?}"), + } + + self.shift += width; + if self.shift % 8 == 0 { + self.pack_bit_fields() + } + } + + fn pack_bit_fields(&mut self) { + assert_eq!(self.shift % 8, 0); + let chunk_type = types::Integer::new(self.shift); + let values = self + .chunk + .drain(..) + .map(|BitField { mut value, field_type, shift }| { + if field_type.width != chunk_type.width { + // We will be combining values with `|`, so we + // need to cast them first. + value = quote! { (#value as #chunk_type) }; + } + if shift > 0 { + let op = quote!(<<); + let shift = proc_macro2::Literal::usize_unsuffixed(shift); + value = quote! { (#value #op #shift) }; + } + value + }) + .collect::<Vec<_>>(); + + match values.as_slice() { + [] => { + let span = format_ident!("{}", self.span); + let count = syn::Index::from(self.shift / 8); + self.code.push(quote! { + #span.put_bytes(0, #count); + }); + } + [value] => { + let put = types::put_uint(self.endianness, value, self.shift, self.span); + self.code.push(quote! { + #put; + }); + } + _ => { + let put = types::put_uint(self.endianness, "e!(value), self.shift, self.span); + self.code.push(quote! { + let value = #(#values)|*; + #put; + }); + } + } + + self.shift = 0; + } + + fn add_array_field( + &mut self, + id: &str, + width: Option<usize>, + padding_size: Option<usize>, + decl: Option<&ast::Decl>, + ) { + let span = format_ident!("{}", self.span); + let serialize = match width { + Some(width) => { + let value = quote!(*elem); + types::put_uint(self.endianness, &value, width, self.span) + } + None => { + if let Some(ast::DeclDesc::Enum { width, .. }) = decl.map(|decl| &decl.desc) { + let element_type = types::Integer::new(*width); + types::put_uint( + self.endianness, + "e!(#element_type::from(elem)), + *width, + self.span, + ) + } else { + quote! { + elem.write_to(#span)? + } + } + } + }; + + let packet_name = self.packet_name; + let name = id; + let id = id.to_ident(); + + if let Some(padding_size) = padding_size { + let padding_octets = padding_size / 8; + let element_width = match &width { + Some(width) => Some(*width), + None => self.schema.decl_size(decl.unwrap().key).static_(), + }; + + let array_size = match element_width { + Some(element_width) => { + let element_size = proc_macro2::Literal::usize_unsuffixed(element_width / 8); + quote! { self.#id.len() * #element_size } + } + _ => { + quote! { self.#id.iter().fold(0, |size, elem| size + elem.get_size()) } + } + }; + + self.code.push(quote! { + let array_size = #array_size; + if array_size > #padding_octets { + return Err(EncodeError::SizeOverflow { + packet: #packet_name, + field: #name, + size: array_size, + maximum_size: #padding_octets, + }) + } + for elem in &self.#id { + #serialize; + } + #span.put_bytes(0, #padding_octets - array_size); + }); + } else { + self.code.push(quote! { + for elem in &self.#id { + #serialize; + } + }); + } + } + + fn add_typedef_field(&mut self, id: &str, type_id: &str) { + assert_eq!(self.shift, 0, "Typedef field does not start on an octet boundary"); + let decl = self.scope.typedef[type_id]; + if let ast::DeclDesc::Struct { parent_id: Some(_), .. } = &decl.desc { + panic!("Derived struct used in typedef field"); + } + + let id = id.to_ident(); + let span = format_ident!("{}", self.span); + + self.code.push(match &decl.desc { + ast::DeclDesc::Checksum { .. } => todo!(), + ast::DeclDesc::CustomField { width: Some(width), .. } => { + let backing_type = types::Integer::new(*width); + let put_uint = types::put_uint( + self.endianness, + "e! { #backing_type::from(self.#id) }, + *width, + self.span, + ); + quote! { + #put_uint; + } + } + ast::DeclDesc::Struct { .. } => quote! { + self.#id.write_to(#span)?; + }, + _ => unreachable!(), + }); + } + + fn add_payload_field(&mut self) { + if self.shift != 0 && self.endianness == ast::EndiannessValue::BigEndian { + panic!("Payload field does not start on an octet boundary"); + } + + let decl = self.scope.typedef[self.packet_name]; + let is_packet = matches!(&decl.desc, ast::DeclDesc::Packet { .. }); + + let child_ids = self + .scope + .iter_children(decl) + .map(|child| child.id().unwrap().to_ident()) + .collect::<Vec<_>>(); + + let span = format_ident!("{}", self.span); + if self.shift == 0 { + if is_packet { + let packet_data_child = format_ident!("{}DataChild", self.packet_name); + self.code.push(quote! { + match &self.child { + #(#packet_data_child::#child_ids(child) => child.write_to(#span)?,)* + #packet_data_child::Payload(payload) => #span.put_slice(payload), + #packet_data_child::None => {}, + } + }) + } else { + self.code.push(quote! { + #span.put_slice(&self.payload); + }); + } + } else { + todo!("Shifted payloads"); + } + } +} + +impl quote::ToTokens for FieldSerializer<'_> { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let code = &self.code; + tokens.extend(quote! { + #(#code)* + }); + } +} diff --git a/src/bin/generate-canonical-tests.rs b/src/backends/rust_legacy/test.rs index 1e18490..77bfe2a 100644 --- a/src/bin/generate-canonical-tests.rs +++ b/src/backends/rust_legacy/test.rs @@ -58,14 +58,13 @@ fn to_json<T: Serialize>(value: &T) -> syn::LitStr { syn::parse_str::<syn::LitStr>(&format!("r#\" {json} \"#")).unwrap() } -fn generate_unit_tests(input: &str, packet_names: &[&str], module_name: &str) { +fn generate_unit_tests(input: &str, packet_names: &[&str]) -> Result<String, String> { eprintln!("Reading test vectors from {input}, will use {} packets", packet_names.len()); let data = std::fs::read_to_string(input) .unwrap_or_else(|err| panic!("Could not read {input}: {err}")); let packets: Vec<Packet> = serde_json::from_str(&data).expect("Could not parse JSON"); - let module = syn::parse_str::<syn::Path>(module_name).unwrap(); let mut tests = Vec::new(); for packet in &packets { for (i, test_vector) in packet.tests.iter().enumerate() { @@ -111,17 +110,17 @@ fn generate_unit_tests(input: &str, packet_names: &[&str], module_name: &str) { #[test] fn #parse_test_name() { let packed = #packed; - let actual = #module::#packet_name::parse(&packed).unwrap(); + let actual = #packet_name::parse(&packed).unwrap(); #(#assertions)* } #[test] fn #serialize_test_name() { - let builder: #module::#builder_name = serde_json::from_str(#json) + let builder: #builder_name = serde_json::from_str(#json) .expect("Could not create builder from canonical JSON data"); let packet = builder.build(); let packed: Vec<u8> = #packed; - assert_eq!(packet.to_vec(), packed); + assert_eq!(packet.encode_to_vec(), Ok(packed)); } }); } @@ -129,24 +128,25 @@ fn generate_unit_tests(input: &str, packet_names: &[&str], module_name: &str) { // TODO(mgeisler): make the generated code clean from warnings. let code = quote! { - #![allow(warnings, missing_docs)] - - use pdl_runtime::Packet; - use serde_json::json; - - #(#tests)* + #[allow(warnings, missing_docs)] + #[cfg(test)] + mod test { + use pdl_runtime::Packet; + use serde_json::json; + use super::*; + + #(#tests)* + } }; let syntax_tree = syn::parse2::<syn::File>(code).expect("Could not parse {code:#?}"); - println!("{}", prettyplease::unparse(&syntax_tree)); + Ok(prettyplease::unparse(&syntax_tree)) } -fn main() { - let input_path = std::env::args().nth(1).expect("Need path to JSON file with test vectors"); - let module_name = std::env::args().nth(2).expect("Need name for the generated module"); +pub fn generate_tests(input_file: &str) -> Result<String, String> { // TODO(mgeisler): remove the `packet_names` argument when we // support all canonical packets. generate_unit_tests( - &input_path, + input_file, &[ "EnumChild_A", "EnumChild_B", @@ -241,7 +241,13 @@ fn main() { "Struct_FixedScalar_Field", "Struct_Size_Field", "Struct_Struct_Field", + "Enum_Incomplete_Truncated_Closed", + "Enum_Incomplete_Truncated_Open", + "Enum_Incomplete_Truncated_Closed_WithRange", + "Enum_Incomplete_Truncated_Open_WithRange", + "Enum_Complete_Truncated", + "Enum_Complete_Truncated_WithRange", + "Enum_Complete_WithRange", ], - &module_name, - ); + ) } diff --git a/src/backends/rust_legacy/types.rs b/src/backends/rust_legacy/types.rs new file mode 100644 index 0000000..ed746a1 --- /dev/null +++ b/src/backends/rust_legacy/types.rs @@ -0,0 +1,186 @@ +// 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. + +//! Utility functions for dealing with Rust integer types. + +use crate::backends::rust_legacy::ToIdent; +use crate::{analyzer, ast}; +use quote::{format_ident, quote}; + +/// A Rust integer type such as `u8`. +#[derive(Copy, Clone)] +pub struct Integer { + pub width: usize, +} + +impl Integer { + /// Get the Rust integer type for the given bit width. + /// + /// This will round up the size to the nearest Rust integer size. + /// PDL supports integers up to 64 bit, so it is an error to call + /// this with a width larger than 64. + pub fn new(width: usize) -> Integer { + for integer_width in [8, 16, 32, 64] { + if width <= integer_width { + return Integer { width: integer_width }; + } + } + panic!("Cannot construct Integer with width: {width}") + } +} + +impl quote::ToTokens for Integer { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let t: syn::Type = syn::parse_str(&format!("u{}", self.width)) + .expect("Could not parse integer, unsupported width?"); + t.to_tokens(tokens); + } +} + +pub fn rust_type(field: &ast::Field) -> proc_macro2::TokenStream { + match &field.desc { + ast::FieldDesc::Scalar { width, .. } if field.cond.is_some() => { + let field_type = Integer::new(*width); + quote!(Option<#field_type>) + } + ast::FieldDesc::Scalar { width, .. } => { + let field_type = Integer::new(*width); + quote!(#field_type) + } + ast::FieldDesc::Typedef { type_id, .. } if field.cond.is_some() => { + let field_type = type_id.to_ident(); + quote!(Option<#field_type>) + } + ast::FieldDesc::Typedef { type_id, .. } => { + let field_type = type_id.to_ident(); + quote!(#field_type) + } + ast::FieldDesc::Array { width: Some(width), size: Some(size), .. } => { + let field_type = Integer::new(*width); + let size = proc_macro2::Literal::usize_unsuffixed(*size); + quote!([#field_type; #size]) + } + ast::FieldDesc::Array { width: Some(width), size: None, .. } => { + let field_type = Integer::new(*width); + quote!(Vec<#field_type>) + } + ast::FieldDesc::Array { type_id: Some(type_id), size: Some(size), .. } => { + let field_type = type_id.to_ident(); + 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(); + quote!(Vec<#field_type>) + } + //ast::Field::Size { .. } | ast::Field::Count { .. } => quote!(), + _ => todo!("{field:?}"), + } +} + +pub fn rust_borrow(field: &ast::Field, scope: &analyzer::Scope<'_>) -> proc_macro2::TokenStream { + match &field.desc { + ast::FieldDesc::Scalar { .. } => quote!(), + ast::FieldDesc::Typedef { type_id, .. } => match &scope.typedef[type_id].desc { + ast::DeclDesc::Enum { .. } => quote!(), + ast::DeclDesc::Struct { .. } => quote!(&), + ast::DeclDesc::CustomField { .. } => quote!(), + desc => unreachable!("unexpected declaration: {desc:?}"), + }, + ast::FieldDesc::Array { .. } => quote!(&), + _ => todo!(), + } +} + +/// Suffix for `Buf::get_*` and `BufMut::put_*` methods when reading a +/// value with the given `width`. +fn endianness_suffix(endianness: ast::EndiannessValue, width: usize) -> &'static str { + if width > 8 && endianness == ast::EndiannessValue::LittleEndian { + "_le" + } else { + "" + } +} + +/// Parse an unsigned integer with the given `width`. +/// +/// The generated code requires that `span` is a mutable `bytes::Buf` +/// value. +pub fn get_uint( + endianness: ast::EndiannessValue, + width: usize, + span: &proc_macro2::Ident, +) -> proc_macro2::TokenStream { + let suffix = endianness_suffix(endianness, width); + let value_type = Integer::new(width); + if value_type.width == width { + let get_u = format_ident!("get_u{}{}", value_type.width, suffix); + quote! { + #span.get_mut().#get_u() + } + } else { + let get_uint = format_ident!("get_uint{}", suffix); + let value_nbytes = proc_macro2::Literal::usize_unsuffixed(width / 8); + let cast = (value_type.width < 64).then(|| quote!(as #value_type)); + quote! { + #span.get_mut().#get_uint(#value_nbytes) #cast + } + } +} + +/// Write an unsigned integer `value` to `span`. +/// +/// The generated code requires that `span` is a mutable +/// `bytes::BufMut` value. +pub fn put_uint( + endianness: ast::EndiannessValue, + value: &proc_macro2::TokenStream, + width: usize, + span: &proc_macro2::Ident, +) -> proc_macro2::TokenStream { + let suffix = endianness_suffix(endianness, width); + let value_type = Integer::new(width); + if value_type.width == width { + let put_u = format_ident!("put_u{}{}", width, suffix); + quote! { + #span.#put_u(#value) + } + } else { + let put_uint = format_ident!("put_uint{}", suffix); + let value_nbytes = proc_macro2::Literal::usize_unsuffixed(width / 8); + let cast = (value_type.width < 64).then(|| quote!(as u64)); + quote! { + #span.#put_uint(#value #cast, #value_nbytes) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_integer_new() { + assert_eq!(Integer::new(0).width, 8); + assert_eq!(Integer::new(8).width, 8); + assert_eq!(Integer::new(9).width, 16); + assert_eq!(Integer::new(64).width, 64); + } + + #[test] + #[should_panic] + fn test_integer_new_panics_on_large_width() { + Integer::new(65); + } +} diff --git a/src/backends/rust_no_allocation/mod.rs b/src/backends/rust_no_allocation/mod.rs index c98bc12..8bf7e57 100644 --- a/src/backends/rust_no_allocation/mod.rs +++ b/src/backends/rust_no_allocation/mod.rs @@ -37,7 +37,6 @@ use proc_macro2::TokenStream; use quote::quote; use crate::ast; -use crate::parser; use self::{ enums::generate_enum, packet_parser::generate_packet, @@ -46,7 +45,7 @@ use self::{ use super::intermediate::Schema; -pub fn generate(file: &parser::ast::File, schema: &Schema) -> Result<String, String> { +pub fn generate(file: &ast::File, schema: &Schema) -> Result<String, String> { match file.endianness.value { ast::EndiannessValue::LittleEndian => {} _ => unimplemented!("Only little_endian endianness supported"), @@ -80,7 +79,7 @@ pub fn generate(file: &parser::ast::File, schema: &Schema) -> Result<String, Str } fn generate_decl( - decl: &parser::ast::Decl, + decl: &ast::Decl, schema: &Schema, children: &HashMap<&str, Vec<&str>>, ) -> Result<TokenStream, String> { diff --git a/src/backends/rust_no_allocation/packet_parser.rs b/src/backends/rust_no_allocation/packet_parser.rs index bd07630..1f9fc0f 100644 --- a/src/backends/rust_no_allocation/packet_parser.rs +++ b/src/backends/rust_no_allocation/packet_parser.rs @@ -18,7 +18,6 @@ use proc_macro2::TokenStream; use quote::{format_ident, quote}; use crate::ast; -use crate::parser; use crate::backends::intermediate::{ ComputedOffsetId, ComputedValueId, PacketOrStruct, PacketOrStructLength, Schema, @@ -29,7 +28,7 @@ use super::utils::get_integer_type; pub fn generate_packet( id: &str, - fields: &[parser::ast::Field], + fields: &[ast::Field], parent_id: Option<&str>, schema: &Schema, curr_schema: &PacketOrStruct, diff --git a/src/backends/rust_no_allocation/packet_serializer.rs b/src/backends/rust_no_allocation/packet_serializer.rs index c088b75..7b06944 100644 --- a/src/backends/rust_no_allocation/packet_serializer.rs +++ b/src/backends/rust_no_allocation/packet_serializer.rs @@ -23,7 +23,6 @@ use crate::{ intermediate::{ComputedValue, ComputedValueId, PacketOrStruct, Schema}, rust_no_allocation::utils::get_integer_type, }, - parser, }; fn standardize_child(id: &str) -> &str { @@ -36,7 +35,7 @@ fn standardize_child(id: &str) -> &str { pub fn generate_packet_serializer( id: &str, parent_id: Option<&str>, - fields: &[parser::ast::Field], + fields: &[ast::Field], schema: &Schema, curr_schema: &PacketOrStruct, children: &HashMap<&str, Vec<&str>>, diff --git a/src/backends/rust_no_allocation/utils.rs b/src/backends/rust_no_allocation/utils.rs index a9286de..ffb7cb0 100644 --- a/src/backends/rust_no_allocation/utils.rs +++ b/src/backends/rust_no_allocation/utils.rs @@ -23,3 +23,14 @@ pub fn get_integer_type(width: usize) -> Ident { .unwrap_or_else(|| panic!("width {width} is too large")); format_ident!("u{best_width}") } + +/// Generate a block of code. +/// +/// Like `quote!`, but the code block will be followed by an empty +/// line of code. This makes the generated code more readable. +#[macro_export] +macro_rules! quote_block { + ($($tt:tt)*) => { + format!("{}\n\n", ::quote::quote!($($tt)*)) + } +} diff --git a/src/main.rs b/src/main.rs index 8992d29..e8fce66 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,8 +24,8 @@ use pdl_compiler::{analyzer, ast, backends, parser}; enum OutputFormat { JSON, Rust, + RustLegacy, RustNoAlloc, - RustNoAllocTest, } impl std::str::FromStr for OutputFormat { @@ -35,8 +35,8 @@ impl std::str::FromStr for OutputFormat { match input.to_lowercase().as_str() { "json" => Ok(Self::JSON), "rust" => Ok(Self::Rust), + "rust_legacy" => Ok(Self::RustLegacy), "rust_no_alloc" => Ok(Self::RustNoAlloc), - "rust_no_alloc_test" => Ok(Self::RustNoAllocTest), _ => Err(format!("could not parse {:?}, valid option are 'json', 'rust', 'rust_no_alloc', and 'rust_no_alloc_test'.", input)), } } @@ -50,10 +50,18 @@ struct Opt { version: bool, #[argh(option, default = "OutputFormat::JSON")] - /// generate output in this format ("json", "rust", "rust_no_alloc", "rust_no_alloc_test"). The output - /// will be printed on stdout in both cases. + /// generate output in this format ("json", "rust", "rust_legacy", "rust_no_alloc"). + /// The output will be printed on stdout in all cases. + /// The input file is the source PDL file. output_format: OutputFormat, + #[argh(switch)] + /// generate tests for the selected output format. + /// Valid for the output formats "rust_legacy", "rust_no_alloc". + /// The input file must point to a JSON formatterd file with the list of + /// test vectors. + tests: bool, + #[argh(positional)] /// input file. input_file: String, @@ -61,13 +69,15 @@ struct Opt { #[argh(option)] /// exclude declarations from the generated output. exclude_declaration: Vec<String>, + + #[argh(option)] + /// custom_field import paths. + /// For the rust backend this is a path e.g. "module::CustomField" or "super::CustomField". + custom_field: Vec<String>, } /// Remove declarations listed in the input filter. -fn filter_declarations( - file: parser::ast::File, - exclude_declarations: &[String], -) -> parser::ast::File { +fn filter_declarations(file: ast::File, exclude_declarations: &[String]) -> ast::File { ast::File { declarations: file .declarations @@ -80,14 +90,7 @@ fn filter_declarations( } } -fn main() -> Result<(), String> { - let opt: Opt = argh::from_env(); - - if opt.version { - println!("Packet Description Language parser version 1.0"); - return Ok(()); - } - +fn generate_backend(opt: &Opt) -> Result<(), String> { let mut sources = ast::SourceDatabase::new(); match parser::parse_file(&mut sources, &opt.input_file) { Ok(file) => { @@ -111,18 +114,18 @@ fn main() -> Result<(), String> { println!("{}", backends::json::generate(&file).unwrap()) } OutputFormat::Rust => { - println!("{}", backends::rust::generate(&sources, &analyzed_file)) + println!( + "{}", + backends::rust::generate(&sources, &analyzed_file, &opt.custom_field) + ) + } + OutputFormat::RustLegacy => { + println!("{}", backends::rust_legacy::generate(&sources, &analyzed_file)) } OutputFormat::RustNoAlloc => { let schema = backends::intermediate::generate(&file).unwrap(); println!("{}", backends::rust_no_allocation::generate(&file, &schema).unwrap()) } - OutputFormat::RustNoAllocTest => { - println!( - "{}", - backends::rust_no_allocation::test::generate_test_file().unwrap() - ) - } } Ok(()) } @@ -135,3 +138,39 @@ fn main() -> Result<(), String> { } } } + +fn generate_tests(opt: &Opt) -> Result<(), String> { + match opt.output_format { + OutputFormat::Rust => { + println!("{}", backends::rust::test::generate_tests(&opt.input_file)?) + } + OutputFormat::RustLegacy => { + println!("{}", backends::rust_legacy::test::generate_tests(&opt.input_file)?) + } + OutputFormat::RustNoAlloc => { + println!("{}", backends::rust_no_allocation::test::generate_test_file()?) + } + _ => { + return Err(format!( + "Canonical tests cannot be generated for the format {:?}", + opt.output_format + )) + } + } + Ok(()) +} + +fn main() -> Result<(), String> { + let opt: Opt = argh::from_env(); + + if opt.version { + println!("Packet Description Language parser version 1.0"); + return Ok(()); + } + + if opt.tests { + generate_tests(&opt) + } else { + generate_backend(&opt) + } +} diff --git a/src/parser.rs b/src/parser.rs index 29407ff..57b42b4 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -12,28 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +use crate::ast; use codespan_reporting::diagnostic::Diagnostic; use codespan_reporting::files; use pest::iterators::{Pair, Pairs}; use pest::{Parser, Token}; use std::iter::{Filter, Peekable}; -pub mod ast { - use serde::Serialize; - - #[derive(Debug, Serialize, Clone, Default, PartialEq, Eq)] - pub struct Annotation; - - impl crate::ast::Annotation for Annotation { - type FieldAnnotation = (); - type DeclAnnotation = (); - } - - pub type Field = crate::ast::Field<Annotation>; - pub type Decl = crate::ast::Decl<Annotation>; - pub type File = crate::ast::File<Annotation>; -} - // Generate the PDL parser. // // TODO: @@ -191,26 +176,40 @@ pub struct PDLParser; type Node<'i> = Pair<'i, Rule>; type NodeIterator<'i> = Peekable<Filter<Pairs<'i, Rule>, fn(&Node<'i>) -> bool>>; -type Context<'a> = (crate::ast::FileId, &'a Vec<usize>); +struct Context<'a> { + file: ast::FileId, + line_starts: &'a Vec<usize>, + key: std::cell::Cell<usize>, +} trait Helpers<'i> { fn children(self) -> NodeIterator<'i>; - fn as_loc(&self, context: &Context) -> crate::ast::SourceRange; + fn as_loc(&self, context: &Context) -> ast::SourceRange; fn as_string(&self) -> String; fn as_usize(&self) -> Result<usize, String>; } +impl<'a> Context<'a> { + fn field_key(&self) -> ast::FieldKey { + ast::FieldKey(self.key.replace(self.key.get() + 1)) + } + + fn decl_key(&self) -> ast::DeclKey { + ast::DeclKey(self.key.replace(self.key.get() + 1)) + } +} + impl<'i> Helpers<'i> for Node<'i> { fn children(self) -> NodeIterator<'i> { self.into_inner().filter((|n| n.as_rule() != Rule::COMMENT) as fn(&Self) -> bool).peekable() } - fn as_loc(&self, context: &Context) -> crate::ast::SourceRange { + fn as_loc(&self, context: &Context) -> ast::SourceRange { let span = self.as_span(); - crate::ast::SourceRange { - file: context.0, - start: crate::ast::SourceLocation::new(span.start_pos().pos(), context.1), - end: crate::ast::SourceLocation::new(span.end_pos().pos(), context.1), + ast::SourceRange { + file: context.file, + start: ast::SourceLocation::new(span.start_pos().pos(), context.line_starts), + end: ast::SourceLocation::new(span.end_pos().pos(), context.line_starts), } } @@ -297,22 +296,22 @@ fn parse_size_modifier_opt(iter: &mut NodeIterator<'_>) -> Option<String> { maybe(iter, Rule::size_modifier).map(|n| n.as_string()) } -fn parse_endianness(node: Node<'_>, context: &Context) -> Result<crate::ast::Endianness, String> { +fn parse_endianness(node: Node<'_>, context: &Context) -> Result<ast::Endianness, String> { if node.as_rule() != Rule::endianness_declaration { err_unexpected_rule(Rule::endianness_declaration, node.as_rule()) } else { - Ok(crate::ast::Endianness { + Ok(ast::Endianness { loc: node.as_loc(context), value: match node.as_str().trim() { - "little_endian_packets" => crate::ast::EndiannessValue::LittleEndian, - "big_endian_packets" => crate::ast::EndiannessValue::BigEndian, + "little_endian_packets" => ast::EndiannessValue::LittleEndian, + "big_endian_packets" => ast::EndiannessValue::BigEndian, _ => unreachable!(), }, }) } } -fn parse_constraint(node: Node<'_>, context: &Context) -> Result<crate::ast::Constraint, String> { +fn parse_constraint(node: Node<'_>, context: &Context) -> Result<ast::Constraint, String> { if node.as_rule() != Rule::constraint { err_unexpected_rule(Rule::constraint, node.as_rule()) } else { @@ -320,19 +319,19 @@ fn parse_constraint(node: Node<'_>, context: &Context) -> Result<crate::ast::Con let mut children = node.children(); let id = parse_identifier(&mut children)?; let (tag_id, value) = parse_identifier_or_integer(&mut children)?; - Ok(crate::ast::Constraint { id, loc, value, tag_id }) + Ok(ast::Constraint { id, loc, value, tag_id }) } } fn parse_constraint_list_opt( iter: &mut NodeIterator<'_>, context: &Context, -) -> Result<Vec<crate::ast::Constraint>, String> { +) -> Result<Vec<ast::Constraint>, String> { maybe(iter, Rule::constraint_list) .map_or(Ok(vec![]), |n| n.children().map(|n| parse_constraint(n, context)).collect()) } -fn parse_enum_value(node: Node<'_>, context: &Context) -> Result<crate::ast::TagValue, String> { +fn parse_enum_value(node: Node<'_>, context: &Context) -> Result<ast::TagValue, String> { if node.as_rule() != Rule::enum_value { err_unexpected_rule(Rule::enum_value, node.as_rule()) } else { @@ -340,19 +339,19 @@ fn parse_enum_value(node: Node<'_>, context: &Context) -> Result<crate::ast::Tag let mut children = node.children(); let id = parse_identifier(&mut children)?; let value = parse_integer(&mut children)?; - Ok(crate::ast::TagValue { id, loc, value }) + Ok(ast::TagValue { id, loc, value }) } } fn parse_enum_value_list_opt( iter: &mut NodeIterator<'_>, context: &Context, -) -> Result<Vec<crate::ast::TagValue>, String> { +) -> Result<Vec<ast::TagValue>, String> { maybe(iter, Rule::enum_value_list) .map_or(Ok(vec![]), |n| n.children().map(|n| parse_enum_value(n, context)).collect()) } -fn parse_enum_range(node: Node<'_>, context: &Context) -> Result<crate::ast::TagRange, String> { +fn parse_enum_range(node: Node<'_>, context: &Context) -> Result<ast::TagRange, String> { if node.as_rule() != Rule::enum_range { err_unexpected_rule(Rule::enum_range, node.as_rule()) } else { @@ -362,34 +361,34 @@ fn parse_enum_range(node: Node<'_>, context: &Context) -> Result<crate::ast::Tag let start = parse_integer(&mut children)?; let end = parse_integer(&mut children)?; let tags = parse_enum_value_list_opt(&mut children, context)?; - Ok(crate::ast::TagRange { id, loc, range: start..=end, tags }) + Ok(ast::TagRange { id, loc, range: start..=end, tags }) } } -fn parse_enum_other(node: Node<'_>, context: &Context) -> Result<crate::ast::TagOther, String> { +fn parse_enum_other(node: Node<'_>, context: &Context) -> Result<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 }) + Ok(ast::TagOther { id, loc }) } } -fn parse_enum_tag(node: Node<'_>, context: &Context) -> Result<crate::ast::Tag, String> { +fn parse_enum_tag(node: Node<'_>, context: &Context) -> Result<ast::Tag, String> { if node.as_rule() != Rule::enum_tag { err_unexpected_rule(Rule::enum_tag, node.as_rule()) } else { match node.children().next() { Some(node) if node.as_rule() == Rule::enum_value => { - Ok(crate::ast::Tag::Value(parse_enum_value(node, context)?)) + Ok(ast::Tag::Value(parse_enum_value(node, context)?)) } Some(node) if node.as_rule() == Rule::enum_range => { - Ok(crate::ast::Tag::Range(parse_enum_range(node, context)?)) + Ok(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)?)) + Ok(ast::Tag::Other(parse_enum_other(node, context)?)) } Some(node) => Err(format!( "expected rule {:?} or {:?}, got {:?}", @@ -409,7 +408,7 @@ fn parse_enum_tag(node: Node<'_>, context: &Context) -> Result<crate::ast::Tag, fn parse_enum_tag_list( iter: &mut NodeIterator<'_>, context: &Context, -) -> Result<Vec<crate::ast::Tag>, String> { +) -> Result<Vec<ast::Tag>, String> { expect(iter, Rule::enum_tag_list) .and_then(|n| n.children().map(|n| parse_enum_tag(n, context)).collect()) } @@ -421,18 +420,18 @@ fn parse_field(node: Node<'_>, context: &Context) -> Result<ast::Field, String> let cond = children.next(); let rule = desc.as_rule(); let mut children = desc.children(); - Ok(crate::ast::Field { + Ok(ast::Field { loc, - annot: Default::default(), + key: context.field_key(), cond: cond.map(|constraint| parse_constraint(constraint, context)).transpose()?, desc: match rule { Rule::checksum_field => { let field_id = parse_identifier(&mut children)?; - crate::ast::FieldDesc::Checksum { field_id } + ast::FieldDesc::Checksum { field_id } } Rule::padding_field => { let size = parse_integer(&mut children)?; - crate::ast::FieldDesc::Padding { size } + ast::FieldDesc::Padding { size } } Rule::size_field => { let field_id = match children.next() { @@ -443,39 +442,39 @@ fn parse_field(node: Node<'_>, context: &Context) -> Result<ast::Field, String> None => err_missing_rule(Rule::identifier)?, }; let width = parse_integer(&mut children)?; - crate::ast::FieldDesc::Size { field_id, width } + ast::FieldDesc::Size { field_id, width } } Rule::count_field => { let field_id = parse_identifier(&mut children)?; let width = parse_integer(&mut children)?; - crate::ast::FieldDesc::Count { field_id, width } + ast::FieldDesc::Count { field_id, width } } Rule::elementsize_field => { let field_id = parse_identifier(&mut children)?; let width = parse_integer(&mut children)?; - crate::ast::FieldDesc::ElementSize { field_id, width } + ast::FieldDesc::ElementSize { field_id, width } } - Rule::body_field => crate::ast::FieldDesc::Body, + Rule::body_field => ast::FieldDesc::Body, Rule::payload_field => { let size_modifier = parse_size_modifier_opt(&mut children); - crate::ast::FieldDesc::Payload { size_modifier } + ast::FieldDesc::Payload { size_modifier } } Rule::fixed_field => match children.next() { Some(n) if n.as_rule() == Rule::integer => { let value = n.as_usize()?; let width = parse_integer(&mut children)?; - crate::ast::FieldDesc::FixedScalar { width, value } + ast::FieldDesc::FixedScalar { width, value } } Some(n) if n.as_rule() == Rule::identifier => { let tag_id = n.as_string(); let enum_id = parse_identifier(&mut children)?; - crate::ast::FieldDesc::FixedEnum { enum_id, tag_id } + ast::FieldDesc::FixedEnum { enum_id, tag_id } } _ => unreachable!(), }, Rule::reserved_field => { let width = parse_integer(&mut children)?; - crate::ast::FieldDesc::Reserved { width } + ast::FieldDesc::Reserved { width } } Rule::array_field => { let id = parse_identifier(&mut children)?; @@ -493,22 +492,22 @@ fn parse_field(node: Node<'_>, context: &Context) -> Result<ast::Field, String> } None => (None, None), }; - crate::ast::FieldDesc::Array { id, type_id, width, size, size_modifier } + ast::FieldDesc::Array { id, type_id, width, size, size_modifier } } Rule::scalar_field => { let id = parse_identifier(&mut children)?; let width = parse_integer(&mut children)?; - crate::ast::FieldDesc::Scalar { id, width } + ast::FieldDesc::Scalar { id, width } } Rule::typedef_field => { let id = parse_identifier(&mut children)?; let type_id = parse_identifier(&mut children)?; - crate::ast::FieldDesc::Typedef { id, type_id } + ast::FieldDesc::Typedef { id, type_id } } Rule::group_field => { let group_id = parse_identifier(&mut children)?; let constraints = parse_constraint_list_opt(&mut children, context)?; - crate::ast::FieldDesc::Group { group_id, constraints } + ast::FieldDesc::Group { group_id, constraints } } _ => return Err(format!("expected rule *_field, got {:?}", rule)), }, @@ -530,7 +529,7 @@ fn parse_field_list_opt( fn parse_toplevel(root: Node<'_>, context: &Context) -> Result<ast::File, String> { let mut toplevel_comments = vec![]; - let mut file = crate::ast::File::new(context.0); + let mut file = ast::File::new(context.file); let mut comment_start = vec![]; for token in root.clone().tokens() { @@ -538,11 +537,11 @@ fn parse_toplevel(root: Node<'_>, context: &Context) -> Result<ast::File, String Token::Start { rule: Rule::COMMENT, pos } => comment_start.push(pos), Token::End { rule: Rule::COMMENT, pos } => { let start_pos = comment_start.pop().unwrap(); - file.comments.push(crate::ast::Comment { - loc: crate::ast::SourceRange { - file: context.0, - start: crate::ast::SourceLocation::new(start_pos.pos(), context.1), - end: crate::ast::SourceLocation::new(pos.pos(), context.1), + file.comments.push(ast::Comment { + loc: ast::SourceRange { + file: context.file, + start: ast::SourceLocation::new(start_pos.pos(), context.line_starts), + end: ast::SourceLocation::new(pos.pos(), context.line_starts), }, text: start_pos.span(&pos).as_str().to_owned(), }) @@ -562,10 +561,11 @@ fn parse_toplevel(root: Node<'_>, context: &Context) -> Result<ast::File, String let id = parse_identifier(&mut children)?; let width = parse_integer(&mut children)?; let function = parse_string(&mut children)?; - file.declarations.push(crate::ast::Decl::new( + file.declarations.push(ast::Decl { loc, - crate::ast::DeclDesc::Checksum { id, function, width }, - )) + key: context.decl_key(), + desc: ast::DeclDesc::Checksum { id, function, width }, + }) } Rule::custom_field_declaration => { let mut children = node.children(); @@ -573,10 +573,11 @@ fn parse_toplevel(root: Node<'_>, context: &Context) -> Result<ast::File, String let id = parse_identifier(&mut children)?; let width = parse_integer_opt(&mut children)?; let function = parse_string(&mut children)?; - file.declarations.push(crate::ast::Decl::new( + file.declarations.push(ast::Decl { loc, - crate::ast::DeclDesc::CustomField { id, function, width }, - )) + key: context.decl_key(), + desc: ast::DeclDesc::CustomField { id, function, width }, + }) } Rule::enum_declaration => { let mut children = node.children(); @@ -584,10 +585,11 @@ fn parse_toplevel(root: Node<'_>, context: &Context) -> Result<ast::File, String let id = parse_identifier(&mut children)?; let width = parse_integer(&mut children)?; let tags = parse_enum_tag_list(&mut children, context)?; - file.declarations.push(crate::ast::Decl::new( + file.declarations.push(ast::Decl { loc, - crate::ast::DeclDesc::Enum { id, width, tags }, - )) + key: context.decl_key(), + desc: ast::DeclDesc::Enum { id, width, tags }, + }) } Rule::packet_declaration => { let mut children = node.children(); @@ -596,10 +598,11 @@ fn parse_toplevel(root: Node<'_>, context: &Context) -> Result<ast::File, String let parent_id = parse_identifier_opt(&mut children)?; let constraints = parse_constraint_list_opt(&mut children, context)?; let fields = parse_field_list_opt(&mut children, context)?; - file.declarations.push(crate::ast::Decl::new( + file.declarations.push(ast::Decl { loc, - crate::ast::DeclDesc::Packet { id, parent_id, constraints, fields }, - )) + key: context.decl_key(), + desc: ast::DeclDesc::Packet { id, parent_id, constraints, fields }, + }) } Rule::struct_declaration => { let mut children = node.children(); @@ -608,18 +611,22 @@ fn parse_toplevel(root: Node<'_>, context: &Context) -> Result<ast::File, String let parent_id = parse_identifier_opt(&mut children)?; let constraints = parse_constraint_list_opt(&mut children, context)?; let fields = parse_field_list_opt(&mut children, context)?; - file.declarations.push(crate::ast::Decl::new( + file.declarations.push(ast::Decl { loc, - crate::ast::DeclDesc::Struct { id, parent_id, constraints, fields }, - )) + key: context.decl_key(), + desc: ast::DeclDesc::Struct { id, parent_id, constraints, fields }, + }) } Rule::group_declaration => { let mut children = node.children(); expect(&mut children, Rule::GROUP)?; let id = parse_identifier(&mut children)?; let fields = parse_field_list(&mut children, context)?; - file.declarations - .push(crate::ast::Decl::new(loc, crate::ast::DeclDesc::Group { id, fields })) + file.declarations.push(ast::Decl { + loc, + key: context.decl_key(), + desc: ast::DeclDesc::Group { id, fields }, + }) } Rule::test_declaration => {} Rule::EOI => (), @@ -627,6 +634,7 @@ fn parse_toplevel(root: Node<'_>, context: &Context) -> Result<ast::File, String } } file.comments.append(&mut toplevel_comments); + file.max_key = context.key.get(); Ok(file) } @@ -635,10 +643,10 @@ fn parse_toplevel(root: Node<'_>, context: &Context) -> Result<ast::File, String /// The file is added to the compilation database under the provided /// name. pub fn parse_inline( - sources: &mut crate::ast::SourceDatabase, + sources: &mut ast::SourceDatabase, name: &str, source: String, -) -> Result<ast::File, Diagnostic<crate::ast::FileId>> { +) -> Result<ast::File, Diagnostic<ast::FileId>> { let root = PDLParser::parse(Rule::file, &source) .map_err(|e| { Diagnostic::error() @@ -648,7 +656,8 @@ pub fn parse_inline( .unwrap(); let line_starts: Vec<_> = files::line_starts(&source).collect(); let file = sources.add(name.to_owned(), source.clone()); - parse_toplevel(root, &(file, &line_starts)).map_err(|e| Diagnostic::error().with_message(e)) + parse_toplevel(root, &Context { file, line_starts: &line_starts, key: std::cell::Cell::new(0) }) + .map_err(|e| Diagnostic::error().with_message(e)) } /// Parse a new source file. @@ -657,9 +666,9 @@ pub fn parse_inline( /// database. Returns the constructed AST, or a descriptive error /// message in case of syntax error. pub fn parse_file( - sources: &mut crate::ast::SourceDatabase, + sources: &mut ast::SourceDatabase, name: &str, -) -> Result<ast::File, Diagnostic<crate::ast::FileId>> { +) -> Result<ast::File, Diagnostic<ast::FileId>> { let source = std::fs::read_to_string(name).map_err(|e| { Diagnostic::error().with_message(format!("failed to read input file '{}': {}", name, e)) })?; @@ -674,10 +683,10 @@ mod test { fn endianness_is_set() { // The file starts out with a placeholder little-endian value. // This tests that we update it while parsing. - let mut db = crate::ast::SourceDatabase::new(); + let mut db = ast::SourceDatabase::new(); let file = parse_inline(&mut db, "stdin", String::from(" big_endian_packets ")).unwrap(); - assert_eq!(file.endianness.value, crate::ast::EndiannessValue::BigEndian); - assert_ne!(file.endianness.loc, crate::ast::SourceRange::default()); + assert_eq!(file.endianness.value, ast::EndiannessValue::BigEndian); + assert_ne!(file.endianness.loc, ast::SourceRange::default()); } #[test] @@ -709,7 +718,7 @@ mod test { fn test_no_whitespace_between_keywords() { // Validate that the parser rejects inputs where whitespaces // are not applied between alphabetical keywords and identifiers. - let mut db = crate::ast::SourceDatabase::new(); + let mut db = ast::SourceDatabase::new(); assert!(parse_inline( &mut db, "test", diff --git a/tests/canonical/le_rust_test_file.pdl b/tests/canonical/le_rust_test_file.pdl deleted file mode 100644 index cdb20b3..0000000 --- a/tests/canonical/le_rust_test_file.pdl +++ /dev/null @@ -1,573 +0,0 @@ -little_endian_packets - -// Preliminary definitions - -enum MaxDiscriminantEnum : 64 { - Max = 0xffffffffffffffff, -} - -enum Enum7 : 7 { - A = 1, - B = 2, -} - -enum Enum16 : 16 { - A = 0xaabb, - B = 0xccdd, -} - -struct SizedStruct { - a: 8, -} - -struct UnsizedStruct { - _size_(array): 2, - _reserved_: 6, - array: 8[], -} - -packet ScalarParent { - a: 8, - _size_(_payload_): 8, - _payload_ -} - -packet EnumParent { - a: Enum16, - _size_(_payload_): 8, - _payload_ -} - -// Packet bit fields - -// The parser must be able to handle bit fields with scalar values -// up to 64 bits wide. The parser should generate a static size guard. -packet Packet_Scalar_Field { - a: 7, - c: 57, -} - -// The parser must be able to handle bit fields with enum values -// up to 64 bits wide. The parser should generate a static size guard. -packet Packet_Enum_Field { - a: Enum7, - c: 57, -} - -// The parser must be able to handle bit fields with reserved fields -// up to 64 bits wide. The parser should generate a static size guard. -packet Packet_Reserved_Field { - a: 7, - _reserved_: 2, - c: 55, -} - -// The parser must be able to handle bit fields with size fields -// up to 64 bits wide. The parser should generate a static size guard. -packet Packet_Size_Field { - _size_(b): 3, - a: 61, - b: 8[], -} - -// The parser must be able to handle bit fields with count fields -// up to 64 bits wide. The parser should generate a static size guard. -packet Packet_Count_Field { - _count_(b): 3, - a: 61, - b: 8[], -} - -// The parser must be able to handle bit fields with fixed scalar values -// up to 64 bits wide. The parser should generate a static size guard. -packet Packet_FixedScalar_Field { - _fixed_ = 7 : 7, - b: 57, -} - -// The parser must be able to handle bit fields with fixed enum values -// up to 64 bits wide. The parser should generate a static size guard. -packet Packet_FixedEnum_Field { - _fixed_ = A : Enum7, - b: 57, -} - -// Packet payload fields - -// The parser must be able to handle sized payload fields without -// size modifier. -packet Packet_Payload_Field_VariableSize { - _size_(_payload_): 3, - _reserved_: 5, - _payload_ -} - -// The parser must be able to handle payload fields of unkonwn size followed -// by fields of statically known size. The remaining span is integrated -// in the packet. -packet Packet_Payload_Field_UnknownSize { - _payload_, - a: 16, -} - -// The parser must be able to handle payload fields of unkonwn size. -// The remaining span is integrated in the packet. -packet Packet_Payload_Field_UnknownSize_Terminal { - a: 16, - _payload_, -} - -// Packet body fields - -// The parser must be able to handle sized body fields without -// size modifier when the packet has no children. -packet Packet_Body_Field_VariableSize { - _size_(_body_): 3, - _reserved_: 5, - _body_ -} - -// The parser must be able to handle body fields of unkonwn size followed -// by fields of statically known size. The remaining span is integrated -// in the packet. -packet Packet_Body_Field_UnknownSize { - _body_, - a: 16, -} - -// The parser must be able to handle body fields of unkonwn size. -// The remaining span is integrated in the packet. -packet Packet_Body_Field_UnknownSize_Terminal { - a: 16, - _body_, -} - -// Packet typedef fields - -// The parser must be able to handle struct fields. -// The size guard is generated by the Struct parser. -packet Packet_Struct_Field { - a: SizedStruct, - b: UnsizedStruct, -} - - -// Array field configurations. -// Add constructs for all configurations of type, size, and padding: -// -// - type: u8, u16, enum, struct with static size, struct with dynamic size -// - size: constant, with size field, with count field, unspecified -// -// The type u8 is tested separately since it is likely to be handled -// idiomatically by the specific language generators. -packet Packet_Array_Field_ByteElement_ConstantSize { - array: 8[4], -} - -packet Packet_Array_Field_ByteElement_VariableSize { - _size_(array) : 4, - _reserved_: 4, - array: 8[], -} - -packet Packet_Array_Field_ByteElement_VariableCount { - _count_(array) : 4, - _reserved_: 4, - array: 8[], -} - -packet Packet_Array_Field_ByteElement_UnknownSize { - array: 8[], -} - -packet Packet_Array_Field_ScalarElement_ConstantSize { - array: 16[4], -} - -packet Packet_Array_Field_ScalarElement_VariableSize { - _size_(array) : 4, - _reserved_: 4, - array: 16[], -} - -packet Packet_Array_Field_ScalarElement_VariableCount { - _count_(array) : 4, - _reserved_: 4, - array: 16[], -} - -packet Packet_Array_Field_ScalarElement_UnknownSize { - array: 16[], -} - -packet Packet_Array_Field_EnumElement_ConstantSize { - array: Enum16[4], -} - -packet Packet_Array_Field_EnumElement_VariableSize { - _size_(array) : 4, - _reserved_: 4, - array: Enum16[], -} - -packet Packet_Array_Field_EnumElement_VariableCount { - _count_(array) : 4, - _reserved_: 4, - array: Enum16[], -} - -packet Packet_Array_Field_EnumElement_UnknownSize { - array: Enum16[], -} - -packet Packet_Array_Field_SizedElement_ConstantSize { - array: SizedStruct[4], -} - -packet Packet_Array_Field_SizedElement_VariableSize { - _size_(array) : 4, - _reserved_: 4, - array: SizedStruct[], -} - -packet Packet_Array_Field_SizedElement_VariableCount { - _count_(array) : 4, - _reserved_: 4, - array: SizedStruct[], -} - -packet Packet_Array_Field_SizedElement_UnknownSize { - array: SizedStruct[], -} - -packet Packet_Array_Field_UnsizedElement_ConstantSize { - array: UnsizedStruct[4], -} - -packet Packet_Array_Field_UnsizedElement_VariableSize { - _size_(array) : 4, - _reserved_: 4, - array: UnsizedStruct[], -} - -packet Packet_Array_Field_UnsizedElement_VariableCount { - _count_(array) : 4, - _reserved_: 4, - array: UnsizedStruct[], -} - -packet Packet_Array_Field_UnsizedElement_UnknownSize { - array: UnsizedStruct[], -} - -// The parser must be able to handle arrays with padded size. -packet Packet_Array_Field_SizedElement_VariableSize_Padded { - _size_(array) : 4, - _reserved_: 4, - array: 16[], - _padding_ [16], -} - -// The parser must be able to handle arrays with padded size. -packet Packet_Array_Field_UnsizedElement_VariableCount_Padded { - _count_(array) : 8, - array: UnsizedStruct[], - _padding_ [16], -} - -// Packet inheritance - -// The parser must handle specialization into -// any child packet of a parent packet with scalar constraints. -packet ScalarChild_A : ScalarParent (a = 0) { - b: 8, -} - -// The parser must handle specialization into -// any child packet of a parent packet with scalar constraints. -packet ScalarChild_B : ScalarParent (a = 1) { - c: 16, -} - -// The parser must handle specialization into -// any child packet of a parent packet with enum constraints. -packet EnumChild_A : EnumParent (a = A) { - b: 8, -} - -// The parser must handle specialization into -// any child packet of a parent packet with enum constraints. -packet EnumChild_B : EnumParent (a = B) { - c: 16, -} - -// Struct bit fields - -// The parser must be able to handle bit fields with scalar values -// up to 64 bits wide. The parser should generate a static size guard. -struct Struct_Scalar_Field { - a: 7, - c: 57, -} - -// The parser must be able to handle bit fields with enum values -// up to 64 bits wide. The parser should generate a static size guard. -struct Struct_Enum_Field_ { - a: Enum7, - c: 57, -} -packet Struct_Enum_Field { - s: Struct_Enum_Field_, -} - -// The parser must be able to handle bit fields with reserved fields -// up to 64 bits wide. The parser should generate a static size guard. -struct Struct_Reserved_Field_ { - a: 7, - _reserved_: 2, - c: 55, -} -packet Struct_Reserved_Field { - s: Struct_Reserved_Field_, -} - -// The parser must be able to handle bit fields with size fields -// up to 64 bits wide. The parser should generate a static size guard. -struct Struct_Size_Field_ { - _size_(b): 3, - a: 61, - b: 8[], -} -packet Struct_Size_Field { - s: Struct_Size_Field_, -} - -// The parser must be able to handle bit fields with count fields -// up to 64 bits wide. The parser should generate a static size guard. -struct Struct_Count_Field_ { - _count_(b): 3, - a: 61, - b: 8[], -} -packet Struct_Count_Field { - s: Struct_Count_Field_, -} -// The parser must be able to handle bit fields with fixed scalar values -// up to 64 bits wide. The parser should generate a static size guard. -struct Struct_FixedScalar_Field_ { - _fixed_ = 7 : 7, - b: 57, -} -packet Struct_FixedScalar_Field { - s: Struct_FixedScalar_Field_, -} - -// The parser must be able to handle bit fields with fixed enum values -// up to 64 bits wide. The parser should generate a static size guard. -struct Struct_FixedEnum_Field_ { - _fixed_ = A : Enum7, - b: 57, -} -packet Struct_FixedEnum_Field { - s: Struct_FixedEnum_Field_, -} - -// Struct typedef fields - -// The parser must be able to handle struct fields. -// The size guard is generated by the Struct parser. -packet Struct_Struct_Field { - a: SizedStruct, - b: UnsizedStruct, -} - -// Array field configurations. -// Add constructs for all configurations of type, size, and padding: -// -// - type: u8, u16, enum, struct with static size, struct with dynamic size -// - size: constant, with size field, with count field, unspecified -// -// The type u8 is tested separately since it is likely to be handled -// idiomatically by the specific language generators. - -struct Struct_Array_Field_ByteElement_ConstantSize_ { - array: 8[4], -} -packet Struct_Array_Field_ByteElement_ConstantSize { - s: Struct_Array_Field_ByteElement_ConstantSize_, -} - - -struct Struct_Array_Field_ByteElement_VariableSize_ { - _size_(array) : 4, - _reserved_: 4, - array: 8[], -} -packet Struct_Array_Field_ByteElement_VariableSize { - s: Struct_Array_Field_ByteElement_VariableSize_, -} - -struct Struct_Array_Field_ByteElement_VariableCount_ { - _count_(array) : 4, - _reserved_: 4, - array: 8[], -} -packet Struct_Array_Field_ByteElement_VariableCount { - s: Struct_Array_Field_ByteElement_VariableCount_, -} - -struct Struct_Array_Field_ByteElement_UnknownSize_ { - array: 8[], -} -packet Struct_Array_Field_ByteElement_UnknownSize { - s: Struct_Array_Field_ByteElement_UnknownSize_, -} - -struct Struct_Array_Field_ScalarElement_ConstantSize_ { - array: 16[4], -} -packet Struct_Array_Field_ScalarElement_ConstantSize { - s: Struct_Array_Field_ScalarElement_ConstantSize_, -} - -struct Struct_Array_Field_ScalarElement_VariableSize_ { - _size_(array) : 4, - _reserved_: 4, - array: 16[], -} -packet Struct_Array_Field_ScalarElement_VariableSize { - s: Struct_Array_Field_ScalarElement_VariableSize_, -} - -struct Struct_Array_Field_ScalarElement_VariableCount_ { - _count_(array) : 4, - _reserved_: 4, - array: 16[], -} -packet Struct_Array_Field_ScalarElement_VariableCount { - s: Struct_Array_Field_ScalarElement_VariableCount_, -} - -struct Struct_Array_Field_ScalarElement_UnknownSize_ { - array: 16[], -} -packet Struct_Array_Field_ScalarElement_UnknownSize { - s: Struct_Array_Field_ScalarElement_UnknownSize_, -} - -struct Struct_Array_Field_EnumElement_ConstantSize_ { - array: Enum16[4], -} -packet Struct_Array_Field_EnumElement_ConstantSize { - s: Struct_Array_Field_EnumElement_ConstantSize_, -} - -struct Struct_Array_Field_EnumElement_VariableSize_ { - _size_(array) : 4, - _reserved_: 4, - array: Enum16[], -} -packet Struct_Array_Field_EnumElement_VariableSize { - s: Struct_Array_Field_EnumElement_VariableSize_, -} - -struct Struct_Array_Field_EnumElement_VariableCount_ { - _count_(array) : 4, - _reserved_: 4, - array: Enum16[], -} -packet Struct_Array_Field_EnumElement_VariableCount { - s: Struct_Array_Field_EnumElement_VariableCount_, -} - -struct Struct_Array_Field_EnumElement_UnknownSize_ { - array: Enum16[], -} -packet Struct_Array_Field_EnumElement_UnknownSize { - s: Struct_Array_Field_EnumElement_UnknownSize_, -} - -struct Struct_Array_Field_SizedElement_ConstantSize_ { - array: SizedStruct[4], -} -packet Struct_Array_Field_SizedElement_ConstantSize { - s: Struct_Array_Field_SizedElement_ConstantSize_, -} - -struct Struct_Array_Field_SizedElement_VariableSize_ { - _size_(array) : 4, - _reserved_: 4, - array: SizedStruct[], -} -packet Struct_Array_Field_SizedElement_VariableSize { - s: Struct_Array_Field_SizedElement_VariableSize_, -} - -struct Struct_Array_Field_SizedElement_VariableCount_ { - _count_(array) : 4, - _reserved_: 4, - array: SizedStruct[], -} -packet Struct_Array_Field_SizedElement_VariableCount { - s: Struct_Array_Field_SizedElement_VariableCount_, -} - -struct Struct_Array_Field_SizedElement_UnknownSize_ { - array: SizedStruct[], -} -packet Struct_Array_Field_SizedElement_UnknownSize { - s: Struct_Array_Field_SizedElement_UnknownSize_, -} - -struct Struct_Array_Field_UnsizedElement_ConstantSize_ { - array: UnsizedStruct[4], -} -packet Struct_Array_Field_UnsizedElement_ConstantSize { - s: Struct_Array_Field_UnsizedElement_ConstantSize_, -} - -struct Struct_Array_Field_UnsizedElement_VariableSize_ { - _size_(array) : 4, - _reserved_: 4, - array: UnsizedStruct[], -} -packet Struct_Array_Field_UnsizedElement_VariableSize { - s: Struct_Array_Field_UnsizedElement_VariableSize_, -} - -struct Struct_Array_Field_UnsizedElement_VariableCount_ { - _count_(array) : 4, - _reserved_: 4, - array: UnsizedStruct[], -} -packet Struct_Array_Field_UnsizedElement_VariableCount { - s: Struct_Array_Field_UnsizedElement_VariableCount_, -} - -struct Struct_Array_Field_UnsizedElement_UnknownSize_ { - array: UnsizedStruct[], -} -packet Struct_Array_Field_UnsizedElement_UnknownSize { - s: Struct_Array_Field_UnsizedElement_UnknownSize_, -} - -// The parser must be able to handle arrays with padded size. -struct Struct_Array_Field_SizedElement_VariableSize_Padded_ { - _size_(array) : 4, - _reserved_: 4, - array: 16[], - _padding_ [16], -} -packet Struct_Array_Field_SizedElement_VariableSize_Padded { - s: Struct_Array_Field_SizedElement_VariableSize_Padded_, -} - -// The parser must be able to handle arrays with padded size. -struct Struct_Array_Field_UnsizedElement_VariableCount_Padded_ { - _count_(array) : 8, - array: UnsizedStruct[], - _padding_ [16], -} -packet Struct_Array_Field_UnsizedElement_VariableCount_Padded { - s: Struct_Array_Field_UnsizedElement_VariableCount_Padded_, -} diff --git a/tests/canonical/le_test_file.pdl b/tests/canonical/le_test_file.pdl index fa87314..86f9c86 100644 --- a/tests/canonical/le_test_file.pdl +++ b/tests/canonical/le_test_file.pdl @@ -26,6 +26,10 @@ struct UnsizedStruct { array: 8[], } +struct UnknownSizeStruct { + array: 8[], +} + group ScalarGroup { a: 16 } @@ -362,6 +366,36 @@ packet Packet_Array_Field_UnsizedElement_VariableCount_Padded { _padding_ [16], } +packet Packet_Array_Field_VariableElementSize_ConstantSize { + _elementsize_(array): 4, + _reserved_: 4, + array: UnknownSizeStruct[4], +} + +packet Packet_Array_Field_VariableElementSize_VariableSize { + _size_(array) : 4, + _reserved_: 4, + _elementsize_(array): 4, + _reserved_: 4, + array: UnknownSizeStruct[], + tail: 8[], +} + +packet Packet_Array_Field_VariableElementSize_VariableCount { + _count_(array) : 4, + _reserved_: 4, + _elementsize_(array): 4, + _reserved_: 4, + array: UnknownSizeStruct[], + tail: 8[], +} + +packet Packet_Array_Field_VariableElementSize_UnknownSize { + _elementsize_(array): 4, + _reserved_: 4, + array: UnknownSizeStruct[], +} + packet Packet_Optional_Scalar_Field { c0: 1, c1: 1, @@ -838,3 +872,101 @@ struct Struct_Optional_Struct_Field_ { packet Struct_Optional_Struct_Field { s: Struct_Optional_Struct_Field_, } + +// Enum declarations +// +// Test enum declarations with exhaustive configurations for the +// following criterias: +// +// 1. truncated: is the enum width a multiple of 8 or not ? +// this characteristic has an impact for some language generators +// 2. complete: does the enum define all possible values ? +// 3. open: does the enum allow for unknown or undefined values ? +// 4. with range: does the enum use a tag range declarations ? + +enum Enum_Incomplete_Truncated_Closed_ : 3 { + A = 0, + B = 1, +} + +packet Enum_Incomplete_Truncated_Closed { + e: Enum_Incomplete_Truncated_Closed_, + _reserved_ : 5, +} + +enum Enum_Incomplete_Truncated_Open_ : 3 { + A = 0, + B = 1, + UNKNOWN = .. +} + +packet Enum_Incomplete_Truncated_Open { + e: Enum_Incomplete_Truncated_Open_, + _reserved_ : 5, +} + +enum Enum_Incomplete_Truncated_Closed_WithRange_ : 3 { + A = 0, + B = 1..6 { + X = 1, + Y = 2, + } +} + +packet Enum_Incomplete_Truncated_Closed_WithRange { + e: Enum_Incomplete_Truncated_Closed_WithRange_, + _reserved_ : 5, +} + +enum Enum_Incomplete_Truncated_Open_WithRange_ : 3 { + A = 0, + B = 1..6 { + X = 1, + Y = 2, + }, + UNKNOWN = .. +} + +packet Enum_Incomplete_Truncated_Open_WithRange { + e: Enum_Incomplete_Truncated_Open_WithRange_, + _reserved_ : 5, +} + +enum Enum_Complete_Truncated_ : 3 { + A = 0, + B = 1, + C = 2, + D = 3, + E = 4, + F = 5, + G = 6, + H = 7, +} + +packet Enum_Complete_Truncated { + e: Enum_Complete_Truncated_, + _reserved_ : 5, +} + +enum Enum_Complete_Truncated_WithRange_ : 3 { + A = 0, + B = 1..7 { + X = 1, + Y = 2, + } +} + +packet Enum_Complete_Truncated_WithRange { + e: Enum_Complete_Truncated_WithRange_, + _reserved_ : 5, +} + +enum Enum_Complete_WithRange_ : 8 { + A = 0, + B = 1, + C = 2..255, +} + +packet Enum_Complete_WithRange { + e: Enum_Complete_WithRange_, +} diff --git a/tests/canonical/le_test_vectors.json b/tests/canonical/le_test_vectors.json index 9ddff45..287c664 100644 --- a/tests/canonical/le_test_vectors.json +++ b/tests/canonical/le_test_vectors.json @@ -2155,6 +2155,164 @@ ] }, { + "packet": "Packet_Array_Field_VariableElementSize_ConstantSize", + "tests": [ + { + "packed": "012a2b2c2d", + "unpacked": { + "array": [ + { + "array": [42] + }, + { + "array": [43] + }, + { + "array": [44] + }, + { + "array": [45] + } + ] + } + }, + { + "packed": "022a2b2c2d2e2f3031", + "unpacked": { + "array": [ + { + "array": [42, 43] + }, + { + "array": [44, 45] + }, + { + "array": [46, 47] + }, + { + "array": [48, 49] + } + ] + } + } + ] + }, + { + "packet": "Packet_Array_Field_VariableElementSize_VariableSize", + "tests": [ + { + "packed": "01012a2b2c", + "unpacked": { + "array": [ + { + "array": [42] + } + ], + "tail": [43, 44] + } + }, + { + "packed": "02012a2b", + "unpacked": { + "array": [ + { + "array": [42] + }, + { + "array": [43] + } + ], + "tail": [] + } + }, + { + "packed": "02022a2b2c", + "unpacked": { + "array": [ + { + "array": [42, 43] + } + ], + "tail": [44] + } + } + ] + }, + { + "packet": "Packet_Array_Field_VariableElementSize_VariableCount", + "tests": [ + { + "packed": "03012a2b2c2d", + "unpacked": { + "array": [ + { + "array": [42] + }, + { + "array": [43] + }, + { + "array": [44] + } + ], + "tail": [45] + } + }, + { + "packed": "02022a2b2c2d", + "unpacked": { + "array": [ + { + "array": [42, 43] + }, + { + "array": [44, 45] + } + ], + "tail": [] + } + } + ] + }, + { + "packet": "Packet_Array_Field_VariableElementSize_UnknownSize", + "tests": [ + { + "packed": "012a", + "unpacked": { + "array": [ + { + "array": [42] + } + ] + } + }, + { + "packed": "012a2b", + "unpacked": { + "array": [ + { + "array": [42] + }, + { + "array": [43] + } + ] + } + }, + { + "packed": "022a2b", + "unpacked": { + "array": [ + { + "array": [42, 43] + } + ] + } + } + ] + }, + { "packet": "Packet_Optional_Scalar_Field", "tests": [ { @@ -5095,5 +5253,232 @@ } } ] + }, + { + "packet": "Enum_Incomplete_Truncated_Closed", + "tests": [ + { + "packed": "00", + "unpacked": { + "e": 0 + } + }, + { + "packed": "01", + "unpacked": { + "e": 1 + } + } + ] + }, + { + "packet": "Enum_Incomplete_Truncated_Open", + "tests": [ + { + "packed": "00", + "unpacked": { + "e": 0 + } + }, + { + "packed": "01", + "unpacked": { + "e": 1 + } + }, + { + "packed": "02", + "unpacked": { + "e": 2 + } + } + ] + }, + { + "packet": "Enum_Incomplete_Truncated_Closed_WithRange", + "tests": [ + { + "packed": "00", + "unpacked": { + "e": 0 + } + }, + { + "packed": "01", + "unpacked": { + "e": 1 + } + }, + { + "packed": "02", + "unpacked": { + "e": 2 + } + } + ] + }, + { + "packet": "Enum_Incomplete_Truncated_Open_WithRange", + "tests": [ + { + "packed": "00", + "unpacked": { + "e": 0 + } + }, + { + "packed": "01", + "unpacked": { + "e": 1 + } + }, + { + "packed": "02", + "unpacked": { + "e": 2 + } + }, + { + "packed": "03", + "unpacked": { + "e": 3 + } + } + ] + }, + { + "packet": "Enum_Complete_Truncated", + "tests": [ + { + "packed": "00", + "unpacked": { + "e": 0 + } + }, + { + "packed": "01", + "unpacked": { + "e": 1 + } + }, + { + "packed": "02", + "unpacked": { + "e": 2 + } + }, + { + "packed": "03", + "unpacked": { + "e": 3 + } + }, + { + "packed": "04", + "unpacked": { + "e": 4 + } + }, + { + "packed": "05", + "unpacked": { + "e": 5 + } + }, + { + "packed": "06", + "unpacked": { + "e": 6 + } + }, + { + "packed": "07", + "unpacked": { + "e": 7 + } + } + ] + }, + { + "packet": "Enum_Complete_Truncated_WithRange", + "tests": [ + { + "packed": "00", + "unpacked": { + "e": 0 + } + }, + { + "packed": "01", + "unpacked": { + "e": 1 + } + }, + { + "packed": "02", + "unpacked": { + "e": 2 + } + }, + { + "packed": "03", + "unpacked": { + "e": 3 + } + }, + { + "packed": "04", + "unpacked": { + "e": 4 + } + }, + { + "packed": "05", + "unpacked": { + "e": 5 + } + }, + { + "packed": "06", + "unpacked": { + "e": 6 + } + }, + { + "packed": "07", + "unpacked": { + "e": 7 + } + } + ] + }, + { + "packet": "Enum_Complete_WithRange", + "tests": [ + { + "packed": "00", + "unpacked": { + "e": 0 + } + }, + { + "packed": "01", + "unpacked": { + "e": 1 + } + }, + { + "packed": "02", + "unpacked": { + "e": 2 + } + }, + { + "packed": "ff", + "unpacked": { + "e": 255 + } + } + ] } ] diff --git a/tests/compile_rust_generated_files.sh b/tests/compile_rust_generated_files.sh new file mode 100755 index 0000000..8cdd6aa --- /dev/null +++ b/tests/compile_rust_generated_files.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +set -euxo pipefail + +mkdir -p out/ +OUT_DIR="$(pwd)/out" + +# move to `pdl-compiler` directory +cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." &> /dev/null + +mkdir -p "$OUT_DIR/generated_test/src" +./tests/generated_files_compile.sh tests/generated/rust/*.rs > "$OUT_DIR/generated_test/src/lib.rs" + +cat <<EOT > "$OUT_DIR/generated_test/Cargo.toml" +[package] +name = "generated_test" +version = "0.0.0" +publish = false +edition = "2021" + +[features] +default = ["serde"] + +[dependencies] +bytes = {version = "1.4.0", features = ["serde"]} +thiserror = "1.0.47" +serde_json = "1.0.86" + +[dependencies.serde] +version = "1.0.145" +features = ["default", "derive", "serde_derive", "std", "rc"] +optional = true + +[dependencies.pdl-runtime] +path = "../../pdl-runtime" + +[workspace] +EOT + +cd "$OUT_DIR/generated_test" +RUSTFLAGS=-Awarnings cargo build diff --git a/tests/compile_rust_legacy_generated_files.sh b/tests/compile_rust_legacy_generated_files.sh new file mode 100755 index 0000000..a461b8d --- /dev/null +++ b/tests/compile_rust_legacy_generated_files.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +set -euxo pipefail + +mkdir -p out/ +OUT_DIR="$(pwd)/out" + +# move to `pdl-compiler` directory +cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." &> /dev/null + +mkdir -p "$OUT_DIR/generated_test/src" +./tests/generated_files_compile.sh tests/generated/rust_legacy/*.rs > "$OUT_DIR/generated_test/src/lib.rs" + +cat <<EOT > "$OUT_DIR/generated_test/Cargo.toml" +[package] +name = "generated_test" +version = "0.0.0" +publish = false +edition = "2021" + +[features] +default = ["serde"] + +[dependencies] +bytes = {version = "1.4.0", features = ["serde"]} +thiserror = "1.0.47" +serde_json = "1.0.86" + +[dependencies.serde] +version = "1.0.145" +features = ["default", "derive", "serde_derive", "std", "rc"] +optional = true + +[dependencies.pdl-runtime] +path = "../../pdl-runtime" + +[workspace] +EOT + +cd "$OUT_DIR/generated_test" +RUSTFLAGS=-Awarnings cargo build diff --git a/tests/generated/preamble.rs b/tests/generated/preamble.rs index dd11680..ab77b58 100644 --- a/tests/generated/preamble.rs +++ b/tests/generated/preamble.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,3 +18,8 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} diff --git a/tests/generated/rust/custom_field_declaration_big_endian.rs b/tests/generated/rust/custom_field_declaration_big_endian.rs new file mode 100644 index 0000000..e5e9d5b --- /dev/null +++ b/tests/generated/rust/custom_field_declaration_big_endian.rs @@ -0,0 +1,102 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(from = "u32", into = "u32"))] +pub struct ExactSize(u32); +impl From<&ExactSize> for u32 { + fn from(value: &ExactSize) -> u32 { + value.0 + } +} +impl From<ExactSize> for u32 { + fn from(value: ExactSize) -> u32 { + value.0 + } +} +impl Packet for ExactSize { + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.len() < 4 { + return Err(DecodeError::InvalidLengthError { + obj: "ExactSize", + wanted: 4, + got: buf.len(), + }); + } + Ok((buf.get_u32().into(), buf)) + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u32(u32::from(self)); + Ok(()) + } + fn encoded_len(&self) -> usize { + 4 + } +} +impl From<u32> for ExactSize { + fn from(value: u32) -> Self { + ExactSize(value) + } +} +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u32", into = "u32"))] +pub struct TruncatedSize(u32); +impl From<&TruncatedSize> for u32 { + fn from(value: &TruncatedSize) -> u32 { + value.0 + } +} +impl From<TruncatedSize> for u32 { + fn from(value: TruncatedSize) -> u32 { + value.0 + } +} +impl Packet for TruncatedSize { + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.len() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "TruncatedSize", + wanted: 3, + got: buf.len(), + }); + } + Ok(((buf.get_uint(3) as u32).try_into().unwrap(), buf)) + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_uint(u32::from(self) as u64, 3); + Ok(()) + } + fn encoded_len(&self) -> usize { + 3 + } +} +impl TryFrom<u32> for TruncatedSize { + type Error = u32; + fn try_from(value: u32) -> Result<Self, Self::Error> { + if value > 0xff_ffff { Err(value) } else { Ok(TruncatedSize(value)) } + } +} diff --git a/tests/generated/rust/custom_field_declaration_little_endian.rs b/tests/generated/rust/custom_field_declaration_little_endian.rs new file mode 100644 index 0000000..bc1874c --- /dev/null +++ b/tests/generated/rust/custom_field_declaration_little_endian.rs @@ -0,0 +1,102 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(from = "u32", into = "u32"))] +pub struct ExactSize(u32); +impl From<&ExactSize> for u32 { + fn from(value: &ExactSize) -> u32 { + value.0 + } +} +impl From<ExactSize> for u32 { + fn from(value: ExactSize) -> u32 { + value.0 + } +} +impl Packet for ExactSize { + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.len() < 4 { + return Err(DecodeError::InvalidLengthError { + obj: "ExactSize", + wanted: 4, + got: buf.len(), + }); + } + Ok((buf.get_u32_le().into(), buf)) + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u32_le(u32::from(self)); + Ok(()) + } + fn encoded_len(&self) -> usize { + 4 + } +} +impl From<u32> for ExactSize { + fn from(value: u32) -> Self { + ExactSize(value) + } +} +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u32", into = "u32"))] +pub struct TruncatedSize(u32); +impl From<&TruncatedSize> for u32 { + fn from(value: &TruncatedSize) -> u32 { + value.0 + } +} +impl From<TruncatedSize> for u32 { + fn from(value: TruncatedSize) -> u32 { + value.0 + } +} +impl Packet for TruncatedSize { + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.len() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "TruncatedSize", + wanted: 3, + got: buf.len(), + }); + } + Ok(((buf.get_uint_le(3) as u32).try_into().unwrap(), buf)) + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_uint_le(u32::from(self) as u64, 3); + Ok(()) + } + fn encoded_len(&self) -> usize { + 3 + } +} +impl TryFrom<u32> for TruncatedSize { + type Error = u32; + fn try_from(value: u32) -> Result<Self, Self::Error> { + if value > 0xff_ffff { Err(value) } else { Ok(TruncatedSize(value)) } + } +} diff --git a/tests/generated/enum_declaration_big_endian.rs b/tests/generated/rust/enum_declaration_big_endian.rs index bd90591..dcff08e 100644 --- a/tests/generated/enum_declaration_big_endian.rs +++ b/tests/generated/rust/enum_declaration_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum IncompleteTruncatedClosed { } impl TryFrom<u8> for IncompleteTruncatedClosed { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(IncompleteTruncatedClosed::A), 0x1 => Ok(IncompleteTruncatedClosed::B), @@ -94,7 +99,7 @@ pub enum IncompleteTruncatedOpen { } impl TryFrom<u8> for IncompleteTruncatedOpen { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(IncompleteTruncatedOpen::A), 0x1 => Ok(IncompleteTruncatedOpen::B), @@ -163,7 +168,7 @@ pub enum IncompleteTruncatedClosedWithRange { } impl TryFrom<u8> for IncompleteTruncatedClosedWithRange { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(IncompleteTruncatedClosedWithRange::A), 0x1 => Ok(IncompleteTruncatedClosedWithRange::X), @@ -235,7 +240,7 @@ pub enum IncompleteTruncatedOpenWithRange { } impl TryFrom<u8> for IncompleteTruncatedOpenWithRange { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(IncompleteTruncatedOpenWithRange::A), 0x1 => Ok(IncompleteTruncatedOpenWithRange::X), @@ -313,7 +318,7 @@ pub enum CompleteTruncated { } impl TryFrom<u8> for CompleteTruncated { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(CompleteTruncated::A), 0x1 => Ok(CompleteTruncated::B), @@ -392,7 +397,7 @@ pub enum CompleteTruncatedWithRange { } impl TryFrom<u8> for CompleteTruncatedWithRange { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(CompleteTruncatedWithRange::A), 0x1 => Ok(CompleteTruncatedWithRange::X), @@ -462,7 +467,7 @@ pub enum CompleteWithRange { } impl TryFrom<u8> for CompleteWithRange { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(CompleteWithRange::A), 0x1 => Ok(CompleteWithRange::B), diff --git a/tests/generated/enum_declaration_little_endian.rs b/tests/generated/rust/enum_declaration_little_endian.rs index bd90591..dcff08e 100644 --- a/tests/generated/enum_declaration_little_endian.rs +++ b/tests/generated/rust/enum_declaration_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum IncompleteTruncatedClosed { } impl TryFrom<u8> for IncompleteTruncatedClosed { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(IncompleteTruncatedClosed::A), 0x1 => Ok(IncompleteTruncatedClosed::B), @@ -94,7 +99,7 @@ pub enum IncompleteTruncatedOpen { } impl TryFrom<u8> for IncompleteTruncatedOpen { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(IncompleteTruncatedOpen::A), 0x1 => Ok(IncompleteTruncatedOpen::B), @@ -163,7 +168,7 @@ pub enum IncompleteTruncatedClosedWithRange { } impl TryFrom<u8> for IncompleteTruncatedClosedWithRange { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(IncompleteTruncatedClosedWithRange::A), 0x1 => Ok(IncompleteTruncatedClosedWithRange::X), @@ -235,7 +240,7 @@ pub enum IncompleteTruncatedOpenWithRange { } impl TryFrom<u8> for IncompleteTruncatedOpenWithRange { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(IncompleteTruncatedOpenWithRange::A), 0x1 => Ok(IncompleteTruncatedOpenWithRange::X), @@ -313,7 +318,7 @@ pub enum CompleteTruncated { } impl TryFrom<u8> for CompleteTruncated { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(CompleteTruncated::A), 0x1 => Ok(CompleteTruncated::B), @@ -392,7 +397,7 @@ pub enum CompleteTruncatedWithRange { } impl TryFrom<u8> for CompleteTruncatedWithRange { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(CompleteTruncatedWithRange::A), 0x1 => Ok(CompleteTruncatedWithRange::X), @@ -462,7 +467,7 @@ pub enum CompleteWithRange { } impl TryFrom<u8> for CompleteWithRange { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(CompleteWithRange::A), 0x1 => Ok(CompleteWithRange::B), diff --git a/tests/generated/rust/packet_decl_24bit_enum_array_big_endian.rs b/tests/generated/rust/packet_decl_24bit_enum_array_big_endian.rs new file mode 100644 index 0000000..6fe68e4 --- /dev/null +++ b/tests/generated/rust/packet_decl_24bit_enum_array_big_endian.rs @@ -0,0 +1,115 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u32", into = "u32"))] +pub enum Foo { + FooBar = 0x1, + Baz = 0x2, +} +impl TryFrom<u32> for Foo { + type Error = u32; + fn try_from(value: u32) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Foo::FooBar), + 0x2 => Ok(Foo::Baz), + _ => Err(value), + } + } +} +impl From<&Foo> for u32 { + fn from(value: &Foo) -> Self { + match value { + Foo::FooBar => 0x1, + Foo::Baz => 0x2, + } + } +} +impl From<Foo> for u32 { + fn from(value: Foo) -> Self { + (&value).into() + } +} +impl From<Foo> for i32 { + fn from(value: Foo) -> Self { + u32::from(value) as Self + } +} +impl From<Foo> for i64 { + fn from(value: Foo) -> Self { + u32::from(value) as Self + } +} +impl From<Foo> for u64 { + fn from(value: Foo) -> Self { + u32::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: [Foo; 5], +} +impl Bar { + pub fn x(&self) -> &[Foo; 5] { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + self.x.len() * 3 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.x { + buf.put_uint(u32::from(elem) as u64, 3); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 * 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 5 * 3, + got: buf.remaining(), + }); + } + let mut x = Vec::with_capacity(5); + for _ in 0..5 { + x.push( + Foo::try_from(buf.get_uint(3) as u32) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "", + value: unknown_val as u64, + type_: "Foo", + })?, + ) + } + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_24bit_enum_array_little_endian.rs b/tests/generated/rust/packet_decl_24bit_enum_array_little_endian.rs new file mode 100644 index 0000000..2e863dd --- /dev/null +++ b/tests/generated/rust/packet_decl_24bit_enum_array_little_endian.rs @@ -0,0 +1,115 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u32", into = "u32"))] +pub enum Foo { + FooBar = 0x1, + Baz = 0x2, +} +impl TryFrom<u32> for Foo { + type Error = u32; + fn try_from(value: u32) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Foo::FooBar), + 0x2 => Ok(Foo::Baz), + _ => Err(value), + } + } +} +impl From<&Foo> for u32 { + fn from(value: &Foo) -> Self { + match value { + Foo::FooBar => 0x1, + Foo::Baz => 0x2, + } + } +} +impl From<Foo> for u32 { + fn from(value: Foo) -> Self { + (&value).into() + } +} +impl From<Foo> for i32 { + fn from(value: Foo) -> Self { + u32::from(value) as Self + } +} +impl From<Foo> for i64 { + fn from(value: Foo) -> Self { + u32::from(value) as Self + } +} +impl From<Foo> for u64 { + fn from(value: Foo) -> Self { + u32::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: [Foo; 5], +} +impl Bar { + pub fn x(&self) -> &[Foo; 5] { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + self.x.len() * 3 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.x { + buf.put_uint_le(u32::from(elem) as u64, 3); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 * 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 5 * 3, + got: buf.remaining(), + }); + } + let mut x = Vec::with_capacity(5); + for _ in 0..5 { + x.push( + Foo::try_from(buf.get_uint_le(3) as u32) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "", + value: unknown_val as u64, + type_: "Foo", + })?, + ) + } + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_24bit_enum_big_endian.rs b/tests/generated/rust/packet_decl_24bit_enum_big_endian.rs new file mode 100644 index 0000000..ed6b119 --- /dev/null +++ b/tests/generated/rust/packet_decl_24bit_enum_big_endian.rs @@ -0,0 +1,107 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u32", into = "u32"))] +pub enum Foo { + A = 0x1, + B = 0x2, +} +impl TryFrom<u32> for Foo { + type Error = u32; + fn try_from(value: u32) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Foo::A), + 0x2 => Ok(Foo::B), + _ => Err(value), + } + } +} +impl From<&Foo> for u32 { + fn from(value: &Foo) -> Self { + match value { + Foo::A => 0x1, + Foo::B => 0x2, + } + } +} +impl From<Foo> for u32 { + fn from(value: Foo) -> Self { + (&value).into() + } +} +impl From<Foo> for i32 { + fn from(value: Foo) -> Self { + u32::from(value) as Self + } +} +impl From<Foo> for i64 { + fn from(value: Foo) -> Self { + u32::from(value) as Self + } +} +impl From<Foo> for u64 { + fn from(value: Foo) -> Self { + u32::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: Foo, +} +impl Bar { + pub fn x(&self) -> Foo { + self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 3 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_uint(u32::from(self.x()) as u64, 3); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 3, + got: buf.remaining(), + }); + } + let x = Foo::try_from(buf.get_uint(3) as u32) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "x", + value: unknown_val as u64, + type_: "Foo", + })?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_24bit_enum_little_endian.rs b/tests/generated/rust/packet_decl_24bit_enum_little_endian.rs new file mode 100644 index 0000000..d31578c --- /dev/null +++ b/tests/generated/rust/packet_decl_24bit_enum_little_endian.rs @@ -0,0 +1,107 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u32", into = "u32"))] +pub enum Foo { + A = 0x1, + B = 0x2, +} +impl TryFrom<u32> for Foo { + type Error = u32; + fn try_from(value: u32) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Foo::A), + 0x2 => Ok(Foo::B), + _ => Err(value), + } + } +} +impl From<&Foo> for u32 { + fn from(value: &Foo) -> Self { + match value { + Foo::A => 0x1, + Foo::B => 0x2, + } + } +} +impl From<Foo> for u32 { + fn from(value: Foo) -> Self { + (&value).into() + } +} +impl From<Foo> for i32 { + fn from(value: Foo) -> Self { + u32::from(value) as Self + } +} +impl From<Foo> for i64 { + fn from(value: Foo) -> Self { + u32::from(value) as Self + } +} +impl From<Foo> for u64 { + fn from(value: Foo) -> Self { + u32::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: Foo, +} +impl Bar { + pub fn x(&self) -> Foo { + self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 3 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_uint_le(u32::from(self.x()) as u64, 3); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 3, + got: buf.remaining(), + }); + } + let x = Foo::try_from(buf.get_uint_le(3) as u32) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "x", + value: unknown_val as u64, + type_: "Foo", + })?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_24bit_scalar_array_big_endian.rs b/tests/generated/rust/packet_decl_24bit_scalar_array_big_endian.rs new file mode 100644 index 0000000..4cb8e6c --- /dev/null +++ b/tests/generated/rust/packet_decl_24bit_scalar_array_big_endian.rs @@ -0,0 +1,61 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: [u32; 5], +} +impl Foo { + pub fn x(&self) -> &[u32; 5] { + &self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.x.len() * 3 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.x { + buf.put_uint(*elem as u64, 3); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 * 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 5 * 3, + got: buf.remaining(), + }); + } + let mut x = Vec::with_capacity(5); + for _ in 0..5 { + x.push(Ok::<_, DecodeError>(buf.get_uint(3) as u32)?) + } + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_24bit_scalar_array_little_endian.rs b/tests/generated/rust/packet_decl_24bit_scalar_array_little_endian.rs new file mode 100644 index 0000000..08f2cd5 --- /dev/null +++ b/tests/generated/rust/packet_decl_24bit_scalar_array_little_endian.rs @@ -0,0 +1,61 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: [u32; 5], +} +impl Foo { + pub fn x(&self) -> &[u32; 5] { + &self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.x.len() * 3 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.x { + buf.put_uint_le(*elem as u64, 3); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 * 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 5 * 3, + got: buf.remaining(), + }); + } + let mut x = Vec::with_capacity(5); + for _ in 0..5 { + x.push(Ok::<_, DecodeError>(buf.get_uint_le(3) as u32)?) + } + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_24bit_scalar_big_endian.rs b/tests/generated/rust/packet_decl_24bit_scalar_big_endian.rs new file mode 100644 index 0000000..d00b083 --- /dev/null +++ b/tests/generated/rust/packet_decl_24bit_scalar_big_endian.rs @@ -0,0 +1,63 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: u32, +} +impl Foo { + pub fn x(&self) -> u32 { + self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 3 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.x() > 0xff_ffff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "x", + value: self.x() as u64, + maximum_value: 0xff_ffff as u64, + }); + } + buf.put_uint(self.x() as u64, 3); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let x = buf.get_uint(3) as u32; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_24bit_scalar_little_endian.rs b/tests/generated/rust/packet_decl_24bit_scalar_little_endian.rs new file mode 100644 index 0000000..1959bab --- /dev/null +++ b/tests/generated/rust/packet_decl_24bit_scalar_little_endian.rs @@ -0,0 +1,63 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: u32, +} +impl Foo { + pub fn x(&self) -> u32 { + self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 3 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.x() > 0xff_ffff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "x", + value: self.x() as u64, + maximum_value: 0xff_ffff as u64, + }); + } + buf.put_uint_le(self.x() as u64, 3); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let x = buf.get_uint_le(3) as u32; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_64bit_enum_array_big_endian.rs b/tests/generated/rust/packet_decl_64bit_enum_array_big_endian.rs new file mode 100644 index 0000000..f46a9bf --- /dev/null +++ b/tests/generated/rust/packet_decl_64bit_enum_array_big_endian.rs @@ -0,0 +1,100 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u64", into = "u64"))] +pub enum Foo { + FooBar = 0x1, + Baz = 0x2, +} +impl TryFrom<u64> for Foo { + type Error = u64; + fn try_from(value: u64) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Foo::FooBar), + 0x2 => Ok(Foo::Baz), + _ => Err(value), + } + } +} +impl From<&Foo> for u64 { + fn from(value: &Foo) -> Self { + match value { + Foo::FooBar => 0x1, + Foo::Baz => 0x2, + } + } +} +impl From<Foo> for u64 { + fn from(value: Foo) -> Self { + (&value).into() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: [Foo; 7], +} +impl Bar { + pub fn x(&self) -> &[Foo; 7] { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + self.x.len() * 8 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.x { + buf.put_u64(u64::from(elem)); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 7 * 8 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 7 * 8, + got: buf.remaining(), + }); + } + let mut x = Vec::with_capacity(7); + for _ in 0..7 { + x.push( + Foo::try_from(buf.get_u64()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "", + value: unknown_val as u64, + type_: "Foo", + })?, + ) + } + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_64bit_enum_array_little_endian.rs b/tests/generated/rust/packet_decl_64bit_enum_array_little_endian.rs new file mode 100644 index 0000000..ee0ae20 --- /dev/null +++ b/tests/generated/rust/packet_decl_64bit_enum_array_little_endian.rs @@ -0,0 +1,100 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u64", into = "u64"))] +pub enum Foo { + FooBar = 0x1, + Baz = 0x2, +} +impl TryFrom<u64> for Foo { + type Error = u64; + fn try_from(value: u64) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Foo::FooBar), + 0x2 => Ok(Foo::Baz), + _ => Err(value), + } + } +} +impl From<&Foo> for u64 { + fn from(value: &Foo) -> Self { + match value { + Foo::FooBar => 0x1, + Foo::Baz => 0x2, + } + } +} +impl From<Foo> for u64 { + fn from(value: Foo) -> Self { + (&value).into() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: [Foo; 7], +} +impl Bar { + pub fn x(&self) -> &[Foo; 7] { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + self.x.len() * 8 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.x { + buf.put_u64_le(u64::from(elem)); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 7 * 8 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 7 * 8, + got: buf.remaining(), + }); + } + let mut x = Vec::with_capacity(7); + for _ in 0..7 { + x.push( + Foo::try_from(buf.get_u64_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "", + value: unknown_val as u64, + type_: "Foo", + })?, + ) + } + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_64bit_enum_big_endian.rs b/tests/generated/rust/packet_decl_64bit_enum_big_endian.rs new file mode 100644 index 0000000..3858625 --- /dev/null +++ b/tests/generated/rust/packet_decl_64bit_enum_big_endian.rs @@ -0,0 +1,92 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u64", into = "u64"))] +pub enum Foo { + A = 0x1, + B = 0x2, +} +impl TryFrom<u64> for Foo { + type Error = u64; + fn try_from(value: u64) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Foo::A), + 0x2 => Ok(Foo::B), + _ => Err(value), + } + } +} +impl From<&Foo> for u64 { + fn from(value: &Foo) -> Self { + match value { + Foo::A => 0x1, + Foo::B => 0x2, + } + } +} +impl From<Foo> for u64 { + fn from(value: Foo) -> Self { + (&value).into() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: Foo, +} +impl Bar { + pub fn x(&self) -> Foo { + self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 8 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u64(u64::from(self.x())); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 8 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 8, + got: buf.remaining(), + }); + } + let x = Foo::try_from(buf.get_u64()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "x", + value: unknown_val as u64, + type_: "Foo", + })?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_64bit_enum_little_endian.rs b/tests/generated/rust/packet_decl_64bit_enum_little_endian.rs new file mode 100644 index 0000000..aa34078 --- /dev/null +++ b/tests/generated/rust/packet_decl_64bit_enum_little_endian.rs @@ -0,0 +1,92 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u64", into = "u64"))] +pub enum Foo { + A = 0x1, + B = 0x2, +} +impl TryFrom<u64> for Foo { + type Error = u64; + fn try_from(value: u64) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Foo::A), + 0x2 => Ok(Foo::B), + _ => Err(value), + } + } +} +impl From<&Foo> for u64 { + fn from(value: &Foo) -> Self { + match value { + Foo::A => 0x1, + Foo::B => 0x2, + } + } +} +impl From<Foo> for u64 { + fn from(value: Foo) -> Self { + (&value).into() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: Foo, +} +impl Bar { + pub fn x(&self) -> Foo { + self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 8 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u64_le(u64::from(self.x())); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 8 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 8, + got: buf.remaining(), + }); + } + let x = Foo::try_from(buf.get_u64_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "x", + value: unknown_val as u64, + type_: "Foo", + })?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_64bit_scalar_array_big_endian.rs b/tests/generated/rust/packet_decl_64bit_scalar_array_big_endian.rs new file mode 100644 index 0000000..666de4b --- /dev/null +++ b/tests/generated/rust/packet_decl_64bit_scalar_array_big_endian.rs @@ -0,0 +1,61 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: [u64; 7], +} +impl Foo { + pub fn x(&self) -> &[u64; 7] { + &self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.x.len() * 8 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.x { + buf.put_u64(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 7 * 8 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 7 * 8, + got: buf.remaining(), + }); + } + let mut x = Vec::with_capacity(7); + for _ in 0..7 { + x.push(Ok::<_, DecodeError>(buf.get_u64())?) + } + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_64bit_scalar_array_little_endian.rs b/tests/generated/rust/packet_decl_64bit_scalar_array_little_endian.rs new file mode 100644 index 0000000..a5ad742 --- /dev/null +++ b/tests/generated/rust/packet_decl_64bit_scalar_array_little_endian.rs @@ -0,0 +1,61 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: [u64; 7], +} +impl Foo { + pub fn x(&self) -> &[u64; 7] { + &self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.x.len() * 8 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.x { + buf.put_u64_le(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 7 * 8 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 7 * 8, + got: buf.remaining(), + }); + } + let mut x = Vec::with_capacity(7); + for _ in 0..7 { + x.push(Ok::<_, DecodeError>(buf.get_u64_le())?) + } + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_64bit_scalar_big_endian.rs b/tests/generated/rust/packet_decl_64bit_scalar_big_endian.rs new file mode 100644 index 0000000..38c4e71 --- /dev/null +++ b/tests/generated/rust/packet_decl_64bit_scalar_big_endian.rs @@ -0,0 +1,55 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: u64, +} +impl Foo { + pub fn x(&self) -> u64 { + self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 8 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u64(self.x()); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 8 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 8, + got: buf.remaining(), + }); + } + let x = buf.get_u64(); + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_64bit_scalar_little_endian.rs b/tests/generated/rust/packet_decl_64bit_scalar_little_endian.rs new file mode 100644 index 0000000..d993814 --- /dev/null +++ b/tests/generated/rust/packet_decl_64bit_scalar_little_endian.rs @@ -0,0 +1,55 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: u64, +} +impl Foo { + pub fn x(&self) -> u64 { + self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 8 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u64_le(self.x()); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 8 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 8, + got: buf.remaining(), + }); + } + let x = buf.get_u64_le(); + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_8bit_enum_array_big_endian.rs b/tests/generated/rust/packet_decl_8bit_enum_array_big_endian.rs new file mode 100644 index 0000000..e48e5fc --- /dev/null +++ b/tests/generated/rust/packet_decl_8bit_enum_array_big_endian.rs @@ -0,0 +1,130 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[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 Foo { + FooBar = 0x1, + Baz = 0x2, +} +impl TryFrom<u8> for Foo { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Foo::FooBar), + 0x2 => Ok(Foo::Baz), + _ => Err(value), + } + } +} +impl From<&Foo> for u8 { + fn from(value: &Foo) -> Self { + match value { + Foo::FooBar => 0x1, + Foo::Baz => 0x2, + } + } +} +impl From<Foo> for u8 { + fn from(value: Foo) -> Self { + (&value).into() + } +} +impl From<Foo> for i16 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for i32 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for i64 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for u16 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for u32 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for u64 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: [Foo; 3], +} +impl Bar { + pub fn x(&self) -> &[Foo; 3] { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + self.x.len() * 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.x { + buf.put_u8(u8::from(elem)); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 3, + got: buf.remaining(), + }); + } + let mut x = Vec::with_capacity(3); + for _ in 0..3 { + x.push( + Foo::try_from(buf.get_u8()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "", + value: unknown_val as u64, + type_: "Foo", + })?, + ) + } + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_8bit_enum_array_little_endian.rs b/tests/generated/rust/packet_decl_8bit_enum_array_little_endian.rs new file mode 100644 index 0000000..e48e5fc --- /dev/null +++ b/tests/generated/rust/packet_decl_8bit_enum_array_little_endian.rs @@ -0,0 +1,130 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[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 Foo { + FooBar = 0x1, + Baz = 0x2, +} +impl TryFrom<u8> for Foo { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Foo::FooBar), + 0x2 => Ok(Foo::Baz), + _ => Err(value), + } + } +} +impl From<&Foo> for u8 { + fn from(value: &Foo) -> Self { + match value { + Foo::FooBar => 0x1, + Foo::Baz => 0x2, + } + } +} +impl From<Foo> for u8 { + fn from(value: Foo) -> Self { + (&value).into() + } +} +impl From<Foo> for i16 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for i32 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for i64 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for u16 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for u32 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for u64 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: [Foo; 3], +} +impl Bar { + pub fn x(&self) -> &[Foo; 3] { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + self.x.len() * 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.x { + buf.put_u8(u8::from(elem)); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 3, + got: buf.remaining(), + }); + } + let mut x = Vec::with_capacity(3); + for _ in 0..3 { + x.push( + Foo::try_from(buf.get_u8()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "", + value: unknown_val as u64, + type_: "Foo", + })?, + ) + } + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_8bit_enum_big_endian.rs b/tests/generated/rust/packet_decl_8bit_enum_big_endian.rs new file mode 100644 index 0000000..809b880 --- /dev/null +++ b/tests/generated/rust/packet_decl_8bit_enum_big_endian.rs @@ -0,0 +1,122 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[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 Foo { + A = 0x1, + B = 0x2, +} +impl TryFrom<u8> for Foo { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Foo::A), + 0x2 => Ok(Foo::B), + _ => Err(value), + } + } +} +impl From<&Foo> for u8 { + fn from(value: &Foo) -> Self { + match value { + Foo::A => 0x1, + Foo::B => 0x2, + } + } +} +impl From<Foo> for u8 { + fn from(value: Foo) -> Self { + (&value).into() + } +} +impl From<Foo> for i16 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for i32 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for i64 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for u16 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for u32 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for u64 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: Foo, +} +impl Bar { + pub fn x(&self) -> Foo { + self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.x())); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let x = Foo::try_from(buf.get_u8()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "x", + value: unknown_val as u64, + type_: "Foo", + })?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_8bit_enum_little_endian.rs b/tests/generated/rust/packet_decl_8bit_enum_little_endian.rs new file mode 100644 index 0000000..809b880 --- /dev/null +++ b/tests/generated/rust/packet_decl_8bit_enum_little_endian.rs @@ -0,0 +1,122 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[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 Foo { + A = 0x1, + B = 0x2, +} +impl TryFrom<u8> for Foo { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Foo::A), + 0x2 => Ok(Foo::B), + _ => Err(value), + } + } +} +impl From<&Foo> for u8 { + fn from(value: &Foo) -> Self { + match value { + Foo::A => 0x1, + Foo::B => 0x2, + } + } +} +impl From<Foo> for u8 { + fn from(value: Foo) -> Self { + (&value).into() + } +} +impl From<Foo> for i16 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for i32 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for i64 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for u16 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for u32 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +impl From<Foo> for u64 { + fn from(value: Foo) -> Self { + u8::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: Foo, +} +impl Bar { + pub fn x(&self) -> Foo { + self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.x())); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let x = Foo::try_from(buf.get_u8()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "x", + value: unknown_val as u64, + type_: "Foo", + })?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_8bit_scalar_array_big_endian.rs b/tests/generated/rust/packet_decl_8bit_scalar_array_big_endian.rs new file mode 100644 index 0000000..ad91b8d --- /dev/null +++ b/tests/generated/rust/packet_decl_8bit_scalar_array_big_endian.rs @@ -0,0 +1,61 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: [u8; 3], +} +impl Foo { + pub fn x(&self) -> &[u8; 3] { + &self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.x.len() * 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.x { + buf.put_u8(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let mut x = Vec::with_capacity(3); + for _ in 0..3 { + x.push(Ok::<_, DecodeError>(buf.get_u8())?) + } + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_8bit_scalar_array_little_endian.rs b/tests/generated/rust/packet_decl_8bit_scalar_array_little_endian.rs new file mode 100644 index 0000000..ad91b8d --- /dev/null +++ b/tests/generated/rust/packet_decl_8bit_scalar_array_little_endian.rs @@ -0,0 +1,61 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: [u8; 3], +} +impl Foo { + pub fn x(&self) -> &[u8; 3] { + &self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.x.len() * 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.x { + buf.put_u8(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let mut x = Vec::with_capacity(3); + for _ in 0..3 { + x.push(Ok::<_, DecodeError>(buf.get_u8())?) + } + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_8bit_scalar_big_endian.rs b/tests/generated/rust/packet_decl_8bit_scalar_big_endian.rs new file mode 100644 index 0000000..d49959b --- /dev/null +++ b/tests/generated/rust/packet_decl_8bit_scalar_big_endian.rs @@ -0,0 +1,55 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: u8, +} +impl Foo { + pub fn x(&self) -> u8 { + self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.x()); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let x = buf.get_u8(); + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_8bit_scalar_little_endian.rs b/tests/generated/rust/packet_decl_8bit_scalar_little_endian.rs new file mode 100644 index 0000000..d49959b --- /dev/null +++ b/tests/generated/rust/packet_decl_8bit_scalar_little_endian.rs @@ -0,0 +1,55 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: u8, +} +impl Foo { + pub fn x(&self) -> u8 { + self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.x()); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let x = buf.get_u8(); + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_dynamic_count_big_endian.rs b/tests/generated/rust/packet_decl_array_dynamic_count_big_endian.rs new file mode 100644 index 0000000..2c6faa8 --- /dev/null +++ b/tests/generated/rust/packet_decl_array_dynamic_count_big_endian.rs @@ -0,0 +1,91 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub padding: u8, + pub x: Vec<u32>, +} +impl Foo { + pub fn padding(&self) -> u8 { + self.padding + } + pub fn x(&self) -> &Vec<u32> { + &self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 1 + self.x.len() * 3 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.x.len() > 0x1f { + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "x", + count: self.x.len(), + maximum_count: 0x1f, + }); + } + if self.padding() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "padding", + value: self.padding() as u64, + maximum_value: 0x7 as u64, + }); + } + let value = self.x.len() as u8 | (self.padding() << 5); + buf.put_u8(value); + for elem in &self.x { + buf.put_uint(*elem as u64, 3); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let chunk = buf.get_u8(); + let x_count = (chunk & 0x1f) as usize; + let padding = ((chunk >> 5) & 0x7); + if buf.remaining() < x_count * 3usize { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: x_count * 3usize, + got: buf.remaining(), + }); + } + let x = (0..x_count) + .map(|_| Ok::<_, DecodeError>(buf.get_uint(3) as u32)) + .collect::<Result<Vec<_>, DecodeError>>()?; + Ok((Self { padding, x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_dynamic_count_little_endian.rs b/tests/generated/rust/packet_decl_array_dynamic_count_little_endian.rs new file mode 100644 index 0000000..687a614 --- /dev/null +++ b/tests/generated/rust/packet_decl_array_dynamic_count_little_endian.rs @@ -0,0 +1,91 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub padding: u8, + pub x: Vec<u32>, +} +impl Foo { + pub fn padding(&self) -> u8 { + self.padding + } + pub fn x(&self) -> &Vec<u32> { + &self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 1 + self.x.len() * 3 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.x.len() > 0x1f { + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "x", + count: self.x.len(), + maximum_count: 0x1f, + }); + } + if self.padding() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "padding", + value: self.padding() as u64, + maximum_value: 0x7 as u64, + }); + } + let value = self.x.len() as u8 | (self.padding() << 5); + buf.put_u8(value); + for elem in &self.x { + buf.put_uint_le(*elem as u64, 3); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let chunk = buf.get_u8(); + let x_count = (chunk & 0x1f) as usize; + let padding = ((chunk >> 5) & 0x7); + if buf.remaining() < x_count * 3usize { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: x_count * 3usize, + got: buf.remaining(), + }); + } + let x = (0..x_count) + .map(|_| Ok::<_, DecodeError>(buf.get_uint_le(3) as u32)) + .collect::<Result<Vec<_>, DecodeError>>()?; + Ok((Self { padding, x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_dynamic_element_size_big_endian.rs b/tests/generated/rust/packet_decl_array_dynamic_element_size_big_endian.rs new file mode 100644 index 0000000..bd95da3 --- /dev/null +++ b/tests/generated/rust/packet_decl_array_dynamic_element_size_big_endian.rs @@ -0,0 +1,146 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub inner: Vec<u8>, +} +impl Foo { + pub fn inner(&self) -> &Vec<u8> { + &self.inner + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.inner.len() * 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.inner { + buf.put_u8(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let mut inner = Vec::with_capacity(buf.remaining()); + for _ in 0..buf.remaining() { + inner.push(Ok::<_, DecodeError>(buf.get_u8())?); + } + Ok((Self { inner }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub padding: u8, + pub x: Vec<Foo>, +} +impl Bar { + pub fn padding(&self) -> u8 { + self.padding + } + pub fn x(&self) -> &Vec<Foo> { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 1 + self.x.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + let x_element_size = self.x.get(0).map_or(0, Packet::encoded_len); + for (element_index, element) in self.x.iter().enumerate() { + if element.encoded_len() != x_element_size { + return Err(EncodeError::InvalidArrayElementSize { + packet: "Bar", + field: "x", + size: element.encoded_len(), + expected_size: x_element_size, + element_index, + }); + } + } + if x_element_size > 0x1f { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_element_size, + maximum_size: 0x1f, + }); + } + let x_element_size = x_element_size as u8; + if self.padding() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Bar", + field: "padding", + value: self.padding() as u64, + maximum_value: 0x7 as u64, + }); + } + let value = x_element_size | (self.padding() << 5); + buf.put_u8(value); + for elem in &self.x { + elem.encode(buf)?; + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let chunk = buf.get_u8(); + let x_element_size = (chunk & 0x1f) as usize; + let padding = ((chunk >> 5) & 0x7); + if buf.remaining() % x_element_size != 0 { + return Err(DecodeError::InvalidArraySize { + array: buf.remaining(), + element: x_element_size, + }); + } + let x = buf + .chunks(x_element_size) + .take(buf.remaining() / x_element_size) + .map(|mut chunk| { + Foo::decode_mut(&mut chunk) + .and_then(|value| { + if chunk.is_empty() { + Ok(value) + } else { + Err(DecodeError::TrailingBytesInArray { + obj: "Bar", + field: "x", + }) + } + }) + }) + .collect::<Result<Vec<_>, DecodeError>>()?; + buf = &buf[buf.remaining()..]; + Ok((Self { padding, x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_count_big_endian.rs b/tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_count_big_endian.rs new file mode 100644 index 0000000..795f94b --- /dev/null +++ b/tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_count_big_endian.rs @@ -0,0 +1,143 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub inner: Vec<u8>, +} +impl Foo { + pub fn inner(&self) -> &Vec<u8> { + &self.inner + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.inner.len() * 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.inner { + buf.put_u8(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let mut inner = Vec::with_capacity(buf.remaining()); + for _ in 0..buf.remaining() { + inner.push(Ok::<_, DecodeError>(buf.get_u8())?); + } + Ok((Self { inner }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: Vec<Foo>, +} +impl Bar { + pub fn x(&self) -> &Vec<Foo> { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 1 + self.x.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.x.len() > 0xf { + return Err(EncodeError::CountOverflow { + packet: "Bar", + field: "x", + count: self.x.len(), + maximum_count: 0xf, + }); + } + let x_element_size = self.x.get(0).map_or(0, Packet::encoded_len); + for (element_index, element) in self.x.iter().enumerate() { + if element.encoded_len() != x_element_size { + return Err(EncodeError::InvalidArrayElementSize { + packet: "Bar", + field: "x", + size: element.encoded_len(), + expected_size: x_element_size, + element_index, + }); + } + } + if x_element_size > 0xf { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_element_size, + maximum_size: 0xf, + }); + } + let x_element_size = x_element_size as u8; + let value = self.x.len() as u8 | (x_element_size << 4); + buf.put_u8(value); + for elem in &self.x { + elem.encode(buf)?; + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let chunk = buf.get_u8(); + let x_count = (chunk & 0xf) as usize; + let x_element_size = ((chunk >> 4) & 0xf) as usize; + if buf.remaining() < x_count * x_element_size { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: x_count * x_element_size, + got: buf.remaining(), + }); + } + let x = buf + .chunks(x_element_size) + .take(x_count) + .map(|mut chunk| { + Foo::decode_mut(&mut chunk) + .and_then(|value| { + if chunk.is_empty() { + Ok(value) + } else { + Err(DecodeError::TrailingBytesInArray { + obj: "Bar", + field: "x", + }) + } + }) + }) + .collect::<Result<Vec<_>, DecodeError>>()?; + buf = &buf[(x_element_size * x_count)..]; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_count_little_endian.rs b/tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_count_little_endian.rs new file mode 100644 index 0000000..795f94b --- /dev/null +++ b/tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_count_little_endian.rs @@ -0,0 +1,143 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub inner: Vec<u8>, +} +impl Foo { + pub fn inner(&self) -> &Vec<u8> { + &self.inner + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.inner.len() * 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.inner { + buf.put_u8(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let mut inner = Vec::with_capacity(buf.remaining()); + for _ in 0..buf.remaining() { + inner.push(Ok::<_, DecodeError>(buf.get_u8())?); + } + Ok((Self { inner }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: Vec<Foo>, +} +impl Bar { + pub fn x(&self) -> &Vec<Foo> { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 1 + self.x.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.x.len() > 0xf { + return Err(EncodeError::CountOverflow { + packet: "Bar", + field: "x", + count: self.x.len(), + maximum_count: 0xf, + }); + } + let x_element_size = self.x.get(0).map_or(0, Packet::encoded_len); + for (element_index, element) in self.x.iter().enumerate() { + if element.encoded_len() != x_element_size { + return Err(EncodeError::InvalidArrayElementSize { + packet: "Bar", + field: "x", + size: element.encoded_len(), + expected_size: x_element_size, + element_index, + }); + } + } + if x_element_size > 0xf { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_element_size, + maximum_size: 0xf, + }); + } + let x_element_size = x_element_size as u8; + let value = self.x.len() as u8 | (x_element_size << 4); + buf.put_u8(value); + for elem in &self.x { + elem.encode(buf)?; + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let chunk = buf.get_u8(); + let x_count = (chunk & 0xf) as usize; + let x_element_size = ((chunk >> 4) & 0xf) as usize; + if buf.remaining() < x_count * x_element_size { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: x_count * x_element_size, + got: buf.remaining(), + }); + } + let x = buf + .chunks(x_element_size) + .take(x_count) + .map(|mut chunk| { + Foo::decode_mut(&mut chunk) + .and_then(|value| { + if chunk.is_empty() { + Ok(value) + } else { + Err(DecodeError::TrailingBytesInArray { + obj: "Bar", + field: "x", + }) + } + }) + }) + .collect::<Result<Vec<_>, DecodeError>>()?; + buf = &buf[(x_element_size * x_count)..]; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_size_big_endian.rs b/tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_size_big_endian.rs new file mode 100644 index 0000000..aa84e02 --- /dev/null +++ b/tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_size_big_endian.rs @@ -0,0 +1,150 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub inner: Vec<u8>, +} +impl Foo { + pub fn inner(&self) -> &Vec<u8> { + &self.inner + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.inner.len() * 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.inner { + buf.put_u8(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let mut inner = Vec::with_capacity(buf.remaining()); + for _ in 0..buf.remaining() { + inner.push(Ok::<_, DecodeError>(buf.get_u8())?); + } + Ok((Self { inner }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: Vec<Foo>, +} +impl Bar { + pub fn x(&self) -> &Vec<Foo> { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 1 + self.x.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + let x_size = self.x.iter().map(Packet::encoded_len).sum::<usize>(); + if x_size > 0xf { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_size, + maximum_size: 0xf, + }); + } + let x_element_size = self.x.get(0).map_or(0, Packet::encoded_len); + for (element_index, element) in self.x.iter().enumerate() { + if element.encoded_len() != x_element_size { + return Err(EncodeError::InvalidArrayElementSize { + packet: "Bar", + field: "x", + size: element.encoded_len(), + expected_size: x_element_size, + element_index, + }); + } + } + if x_element_size > 0xf { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_element_size, + maximum_size: 0xf, + }); + } + let x_element_size = x_element_size as u8; + let value = x_size as u8 | (x_element_size << 4); + buf.put_u8(value); + for elem in &self.x { + elem.encode(buf)?; + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let chunk = buf.get_u8(); + let x_size = (chunk & 0xf) as usize; + let x_element_size = ((chunk >> 4) & 0xf) as usize; + if buf.remaining() < x_size { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: x_size, + got: buf.remaining(), + }); + } + if x_size % x_element_size != 0 { + return Err(DecodeError::InvalidArraySize { + array: x_size, + element: x_element_size, + }); + } + let x = buf + .chunks(x_element_size) + .take(x_size / x_element_size) + .map(|mut chunk| { + Foo::decode_mut(&mut chunk) + .and_then(|value| { + if chunk.is_empty() { + Ok(value) + } else { + Err(DecodeError::TrailingBytesInArray { + obj: "Bar", + field: "x", + }) + } + }) + }) + .collect::<Result<Vec<_>, DecodeError>>()?; + buf = &buf[x_size..]; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_size_little_endian.rs b/tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_size_little_endian.rs new file mode 100644 index 0000000..aa84e02 --- /dev/null +++ b/tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_size_little_endian.rs @@ -0,0 +1,150 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub inner: Vec<u8>, +} +impl Foo { + pub fn inner(&self) -> &Vec<u8> { + &self.inner + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.inner.len() * 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.inner { + buf.put_u8(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let mut inner = Vec::with_capacity(buf.remaining()); + for _ in 0..buf.remaining() { + inner.push(Ok::<_, DecodeError>(buf.get_u8())?); + } + Ok((Self { inner }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: Vec<Foo>, +} +impl Bar { + pub fn x(&self) -> &Vec<Foo> { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 1 + self.x.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + let x_size = self.x.iter().map(Packet::encoded_len).sum::<usize>(); + if x_size > 0xf { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_size, + maximum_size: 0xf, + }); + } + let x_element_size = self.x.get(0).map_or(0, Packet::encoded_len); + for (element_index, element) in self.x.iter().enumerate() { + if element.encoded_len() != x_element_size { + return Err(EncodeError::InvalidArrayElementSize { + packet: "Bar", + field: "x", + size: element.encoded_len(), + expected_size: x_element_size, + element_index, + }); + } + } + if x_element_size > 0xf { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_element_size, + maximum_size: 0xf, + }); + } + let x_element_size = x_element_size as u8; + let value = x_size as u8 | (x_element_size << 4); + buf.put_u8(value); + for elem in &self.x { + elem.encode(buf)?; + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let chunk = buf.get_u8(); + let x_size = (chunk & 0xf) as usize; + let x_element_size = ((chunk >> 4) & 0xf) as usize; + if buf.remaining() < x_size { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: x_size, + got: buf.remaining(), + }); + } + if x_size % x_element_size != 0 { + return Err(DecodeError::InvalidArraySize { + array: x_size, + element: x_element_size, + }); + } + let x = buf + .chunks(x_element_size) + .take(x_size / x_element_size) + .map(|mut chunk| { + Foo::decode_mut(&mut chunk) + .and_then(|value| { + if chunk.is_empty() { + Ok(value) + } else { + Err(DecodeError::TrailingBytesInArray { + obj: "Bar", + field: "x", + }) + } + }) + }) + .collect::<Result<Vec<_>, DecodeError>>()?; + buf = &buf[x_size..]; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_dynamic_element_size_little_endian.rs b/tests/generated/rust/packet_decl_array_dynamic_element_size_little_endian.rs new file mode 100644 index 0000000..bd95da3 --- /dev/null +++ b/tests/generated/rust/packet_decl_array_dynamic_element_size_little_endian.rs @@ -0,0 +1,146 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub inner: Vec<u8>, +} +impl Foo { + pub fn inner(&self) -> &Vec<u8> { + &self.inner + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.inner.len() * 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.inner { + buf.put_u8(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let mut inner = Vec::with_capacity(buf.remaining()); + for _ in 0..buf.remaining() { + inner.push(Ok::<_, DecodeError>(buf.get_u8())?); + } + Ok((Self { inner }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub padding: u8, + pub x: Vec<Foo>, +} +impl Bar { + pub fn padding(&self) -> u8 { + self.padding + } + pub fn x(&self) -> &Vec<Foo> { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 1 + self.x.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + let x_element_size = self.x.get(0).map_or(0, Packet::encoded_len); + for (element_index, element) in self.x.iter().enumerate() { + if element.encoded_len() != x_element_size { + return Err(EncodeError::InvalidArrayElementSize { + packet: "Bar", + field: "x", + size: element.encoded_len(), + expected_size: x_element_size, + element_index, + }); + } + } + if x_element_size > 0x1f { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_element_size, + maximum_size: 0x1f, + }); + } + let x_element_size = x_element_size as u8; + if self.padding() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Bar", + field: "padding", + value: self.padding() as u64, + maximum_value: 0x7 as u64, + }); + } + let value = x_element_size | (self.padding() << 5); + buf.put_u8(value); + for elem in &self.x { + elem.encode(buf)?; + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let chunk = buf.get_u8(); + let x_element_size = (chunk & 0x1f) as usize; + let padding = ((chunk >> 5) & 0x7); + if buf.remaining() % x_element_size != 0 { + return Err(DecodeError::InvalidArraySize { + array: buf.remaining(), + element: x_element_size, + }); + } + let x = buf + .chunks(x_element_size) + .take(buf.remaining() / x_element_size) + .map(|mut chunk| { + Foo::decode_mut(&mut chunk) + .and_then(|value| { + if chunk.is_empty() { + Ok(value) + } else { + Err(DecodeError::TrailingBytesInArray { + obj: "Bar", + field: "x", + }) + } + }) + }) + .collect::<Result<Vec<_>, DecodeError>>()?; + buf = &buf[buf.remaining()..]; + Ok((Self { padding, x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_1_big_endian.rs b/tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_1_big_endian.rs new file mode 100644 index 0000000..8b38b98 --- /dev/null +++ b/tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_1_big_endian.rs @@ -0,0 +1,148 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub inner: Vec<u8>, +} +impl Foo { + pub fn inner(&self) -> &Vec<u8> { + &self.inner + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.inner.len() * 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.inner { + buf.put_u8(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let mut inner = Vec::with_capacity(buf.remaining()); + for _ in 0..buf.remaining() { + inner.push(Ok::<_, DecodeError>(buf.get_u8())?); + } + Ok((Self { inner }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub padding: u8, + pub x: [Foo; 1], +} +impl Bar { + pub fn padding(&self) -> u8 { + self.padding + } + pub fn x(&self) -> &[Foo; 1] { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 1 + self.x.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + let x_element_size = self.x.get(0).map_or(0, Packet::encoded_len); + for (element_index, element) in self.x.iter().enumerate() { + if element.encoded_len() != x_element_size { + return Err(EncodeError::InvalidArrayElementSize { + packet: "Bar", + field: "x", + size: element.encoded_len(), + expected_size: x_element_size, + element_index, + }); + } + } + if x_element_size > 0x1f { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_element_size, + maximum_size: 0x1f, + }); + } + let x_element_size = x_element_size as u8; + if self.padding() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Bar", + field: "padding", + value: self.padding() as u64, + maximum_value: 0x7 as u64, + }); + } + let value = x_element_size | (self.padding() << 5); + buf.put_u8(value); + for elem in &self.x { + elem.encode(buf)?; + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let chunk = buf.get_u8(); + let x_element_size = (chunk & 0x1f) as usize; + let padding = ((chunk >> 5) & 0x7); + if buf.remaining() < x_element_size { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: x_element_size, + got: buf.remaining(), + }); + } + let x = buf + .chunks(x_element_size) + .take(1usize) + .map(|mut chunk| { + Foo::decode_mut(&mut chunk) + .and_then(|value| { + if chunk.is_empty() { + Ok(value) + } else { + Err(DecodeError::TrailingBytesInArray { + obj: "Bar", + field: "x", + }) + } + }) + }) + .collect::<Result<Vec<_>, DecodeError>>()?; + buf = &buf[x_element_size..]; + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { padding, x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_1_little_endian.rs b/tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_1_little_endian.rs new file mode 100644 index 0000000..8b38b98 --- /dev/null +++ b/tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_1_little_endian.rs @@ -0,0 +1,148 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub inner: Vec<u8>, +} +impl Foo { + pub fn inner(&self) -> &Vec<u8> { + &self.inner + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.inner.len() * 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.inner { + buf.put_u8(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let mut inner = Vec::with_capacity(buf.remaining()); + for _ in 0..buf.remaining() { + inner.push(Ok::<_, DecodeError>(buf.get_u8())?); + } + Ok((Self { inner }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub padding: u8, + pub x: [Foo; 1], +} +impl Bar { + pub fn padding(&self) -> u8 { + self.padding + } + pub fn x(&self) -> &[Foo; 1] { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 1 + self.x.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + let x_element_size = self.x.get(0).map_or(0, Packet::encoded_len); + for (element_index, element) in self.x.iter().enumerate() { + if element.encoded_len() != x_element_size { + return Err(EncodeError::InvalidArrayElementSize { + packet: "Bar", + field: "x", + size: element.encoded_len(), + expected_size: x_element_size, + element_index, + }); + } + } + if x_element_size > 0x1f { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_element_size, + maximum_size: 0x1f, + }); + } + let x_element_size = x_element_size as u8; + if self.padding() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Bar", + field: "padding", + value: self.padding() as u64, + maximum_value: 0x7 as u64, + }); + } + let value = x_element_size | (self.padding() << 5); + buf.put_u8(value); + for elem in &self.x { + elem.encode(buf)?; + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let chunk = buf.get_u8(); + let x_element_size = (chunk & 0x1f) as usize; + let padding = ((chunk >> 5) & 0x7); + if buf.remaining() < x_element_size { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: x_element_size, + got: buf.remaining(), + }); + } + let x = buf + .chunks(x_element_size) + .take(1usize) + .map(|mut chunk| { + Foo::decode_mut(&mut chunk) + .and_then(|value| { + if chunk.is_empty() { + Ok(value) + } else { + Err(DecodeError::TrailingBytesInArray { + obj: "Bar", + field: "x", + }) + } + }) + }) + .collect::<Result<Vec<_>, DecodeError>>()?; + buf = &buf[x_element_size..]; + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { padding, x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_big_endian.rs b/tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_big_endian.rs new file mode 100644 index 0000000..0a86f0e --- /dev/null +++ b/tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_big_endian.rs @@ -0,0 +1,148 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub inner: Vec<u8>, +} +impl Foo { + pub fn inner(&self) -> &Vec<u8> { + &self.inner + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.inner.len() * 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.inner { + buf.put_u8(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let mut inner = Vec::with_capacity(buf.remaining()); + for _ in 0..buf.remaining() { + inner.push(Ok::<_, DecodeError>(buf.get_u8())?); + } + Ok((Self { inner }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub padding: u8, + pub x: [Foo; 4], +} +impl Bar { + pub fn padding(&self) -> u8 { + self.padding + } + pub fn x(&self) -> &[Foo; 4] { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 1 + self.x.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + let x_element_size = self.x.get(0).map_or(0, Packet::encoded_len); + for (element_index, element) in self.x.iter().enumerate() { + if element.encoded_len() != x_element_size { + return Err(EncodeError::InvalidArrayElementSize { + packet: "Bar", + field: "x", + size: element.encoded_len(), + expected_size: x_element_size, + element_index, + }); + } + } + if x_element_size > 0x1f { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_element_size, + maximum_size: 0x1f, + }); + } + let x_element_size = x_element_size as u8; + if self.padding() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Bar", + field: "padding", + value: self.padding() as u64, + maximum_value: 0x7 as u64, + }); + } + let value = x_element_size | (self.padding() << 5); + buf.put_u8(value); + for elem in &self.x { + elem.encode(buf)?; + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let chunk = buf.get_u8(); + let x_element_size = (chunk & 0x1f) as usize; + let padding = ((chunk >> 5) & 0x7); + if buf.remaining() < 4usize * x_element_size { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 4usize * x_element_size, + got: buf.remaining(), + }); + } + let x = buf + .chunks(x_element_size) + .take(4usize) + .map(|mut chunk| { + Foo::decode_mut(&mut chunk) + .and_then(|value| { + if chunk.is_empty() { + Ok(value) + } else { + Err(DecodeError::TrailingBytesInArray { + obj: "Bar", + field: "x", + }) + } + }) + }) + .collect::<Result<Vec<_>, DecodeError>>()?; + buf = &buf[4usize * x_element_size..]; + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { padding, x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_little_endian.rs b/tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_little_endian.rs new file mode 100644 index 0000000..0a86f0e --- /dev/null +++ b/tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_little_endian.rs @@ -0,0 +1,148 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub inner: Vec<u8>, +} +impl Foo { + pub fn inner(&self) -> &Vec<u8> { + &self.inner + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + self.inner.len() * 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + for elem in &self.inner { + buf.put_u8(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let mut inner = Vec::with_capacity(buf.remaining()); + for _ in 0..buf.remaining() { + inner.push(Ok::<_, DecodeError>(buf.get_u8())?); + } + Ok((Self { inner }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub padding: u8, + pub x: [Foo; 4], +} +impl Bar { + pub fn padding(&self) -> u8 { + self.padding + } + pub fn x(&self) -> &[Foo; 4] { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 1 + self.x.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + let x_element_size = self.x.get(0).map_or(0, Packet::encoded_len); + for (element_index, element) in self.x.iter().enumerate() { + if element.encoded_len() != x_element_size { + return Err(EncodeError::InvalidArrayElementSize { + packet: "Bar", + field: "x", + size: element.encoded_len(), + expected_size: x_element_size, + element_index, + }); + } + } + if x_element_size > 0x1f { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_element_size, + maximum_size: 0x1f, + }); + } + let x_element_size = x_element_size as u8; + if self.padding() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Bar", + field: "padding", + value: self.padding() as u64, + maximum_value: 0x7 as u64, + }); + } + let value = x_element_size | (self.padding() << 5); + buf.put_u8(value); + for elem in &self.x { + elem.encode(buf)?; + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let chunk = buf.get_u8(); + let x_element_size = (chunk & 0x1f) as usize; + let padding = ((chunk >> 5) & 0x7); + if buf.remaining() < 4usize * x_element_size { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 4usize * x_element_size, + got: buf.remaining(), + }); + } + let x = buf + .chunks(x_element_size) + .take(4usize) + .map(|mut chunk| { + Foo::decode_mut(&mut chunk) + .and_then(|value| { + if chunk.is_empty() { + Ok(value) + } else { + Err(DecodeError::TrailingBytesInArray { + obj: "Bar", + field: "x", + }) + } + }) + }) + .collect::<Result<Vec<_>, DecodeError>>()?; + buf = &buf[4usize * x_element_size..]; + let x = x.try_into().map_err(|_| DecodeError::InvalidPacketError)?; + Ok((Self { padding, x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_dynamic_size_big_endian.rs b/tests/generated/rust/packet_decl_array_dynamic_size_big_endian.rs new file mode 100644 index 0000000..4c7bb72 --- /dev/null +++ b/tests/generated/rust/packet_decl_array_dynamic_size_big_endian.rs @@ -0,0 +1,99 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub padding: u8, + pub x: Vec<u32>, +} +impl Foo { + pub fn padding(&self) -> u8 { + self.padding + } + pub fn x(&self) -> &Vec<u32> { + &self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 1 + self.x.len() * 3 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if (self.x.len() * 3) > 0x1f { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "x", + size: (self.x.len() * 3), + maximum_size: 0x1f, + }); + } + if self.padding() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "padding", + value: self.padding() as u64, + maximum_value: 0x7 as u64, + }); + } + let value = (self.x.len() * 3) as u8 | (self.padding() << 5); + buf.put_u8(value); + for elem in &self.x { + buf.put_uint(*elem as u64, 3); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let chunk = buf.get_u8(); + let x_size = (chunk & 0x1f) as usize; + let padding = ((chunk >> 5) & 0x7); + if buf.remaining() < x_size { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: x_size, + got: buf.remaining(), + }); + } + if x_size % 3 != 0 { + return Err(DecodeError::InvalidArraySize { + array: x_size, + element: 3, + }); + } + let x_count = x_size / 3; + let mut x = Vec::with_capacity(x_count); + for _ in 0..x_count { + x.push(Ok::<_, DecodeError>(buf.get_uint(3) as u32)?); + } + Ok((Self { padding, x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_dynamic_size_little_endian.rs b/tests/generated/rust/packet_decl_array_dynamic_size_little_endian.rs new file mode 100644 index 0000000..4d226f8 --- /dev/null +++ b/tests/generated/rust/packet_decl_array_dynamic_size_little_endian.rs @@ -0,0 +1,99 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub padding: u8, + pub x: Vec<u32>, +} +impl Foo { + pub fn padding(&self) -> u8 { + self.padding + } + pub fn x(&self) -> &Vec<u32> { + &self.x + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 1 + self.x.len() * 3 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if (self.x.len() * 3) > 0x1f { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "x", + size: (self.x.len() * 3), + maximum_size: 0x1f, + }); + } + if self.padding() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "padding", + value: self.padding() as u64, + maximum_value: 0x7 as u64, + }); + } + let value = (self.x.len() * 3) as u8 | (self.padding() << 5); + buf.put_u8(value); + for elem in &self.x { + buf.put_uint_le(*elem as u64, 3); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let chunk = buf.get_u8(); + let x_size = (chunk & 0x1f) as usize; + let padding = ((chunk >> 5) & 0x7); + if buf.remaining() < x_size { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: x_size, + got: buf.remaining(), + }); + } + if x_size % 3 != 0 { + return Err(DecodeError::InvalidArraySize { + array: x_size, + element: 3, + }); + } + let x_count = x_size / 3; + let mut x = Vec::with_capacity(x_count); + for _ in 0..x_count { + x.push(Ok::<_, DecodeError>(buf.get_uint_le(3) as u32)?); + } + Ok((Self { padding, x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_count_big_endian.rs b/tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_count_big_endian.rs new file mode 100644 index 0000000..d9d7733 --- /dev/null +++ b/tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_count_big_endian.rs @@ -0,0 +1,120 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: Vec<u16>, +} +impl Foo { + pub fn a(&self) -> &Vec<u16> { + &self.a + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 5 + self.a.len() * 2 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.a.len() > 0xff_ffff_ffff_usize { + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "a", + count: self.a.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); + } + buf.put_uint(self.a.len() as u64, 5); + for elem in &self.a { + buf.put_u16(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 5, + got: buf.remaining(), + }); + } + let a_count = buf.get_uint(5) as usize; + if buf.remaining() < a_count * 2usize { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: a_count * 2usize, + got: buf.remaining(), + }); + } + let a = (0..a_count) + .map(|_| Ok::<_, DecodeError>(buf.get_u16())) + .collect::<Result<Vec<_>, DecodeError>>()?; + Ok((Self { a }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: Vec<Foo>, +} +impl Bar { + pub fn x(&self) -> &Vec<Foo> { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 5 + self.x.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.x.len() > 0xff_ffff_ffff_usize { + return Err(EncodeError::CountOverflow { + packet: "Bar", + field: "x", + count: self.x.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); + } + buf.put_uint(self.x.len() as u64, 5); + for elem in &self.x { + elem.encode(buf)?; + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 5, + got: buf.remaining(), + }); + } + let x_count = buf.get_uint(5) as usize; + let x = (0..x_count) + .map(|_| Foo::decode_mut(&mut buf)) + .collect::<Result<Vec<_>, DecodeError>>()?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_count_little_endian.rs b/tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_count_little_endian.rs new file mode 100644 index 0000000..eb249ac --- /dev/null +++ b/tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_count_little_endian.rs @@ -0,0 +1,120 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: Vec<u16>, +} +impl Foo { + pub fn a(&self) -> &Vec<u16> { + &self.a + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 5 + self.a.len() * 2 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.a.len() > 0xff_ffff_ffff_usize { + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "a", + count: self.a.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); + } + buf.put_uint_le(self.a.len() as u64, 5); + for elem in &self.a { + buf.put_u16_le(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 5, + got: buf.remaining(), + }); + } + let a_count = buf.get_uint_le(5) as usize; + if buf.remaining() < a_count * 2usize { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: a_count * 2usize, + got: buf.remaining(), + }); + } + let a = (0..a_count) + .map(|_| Ok::<_, DecodeError>(buf.get_u16_le())) + .collect::<Result<Vec<_>, DecodeError>>()?; + Ok((Self { a }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: Vec<Foo>, +} +impl Bar { + pub fn x(&self) -> &Vec<Foo> { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 5 + self.x.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.x.len() > 0xff_ffff_ffff_usize { + return Err(EncodeError::CountOverflow { + packet: "Bar", + field: "x", + count: self.x.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); + } + buf.put_uint_le(self.x.len() as u64, 5); + for elem in &self.x { + elem.encode(buf)?; + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 5, + got: buf.remaining(), + }); + } + let x_count = buf.get_uint_le(5) as usize; + let x = (0..x_count) + .map(|_| Foo::decode_mut(&mut buf)) + .collect::<Result<Vec<_>, DecodeError>>()?; + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_size_big_endian.rs b/tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_size_big_endian.rs new file mode 100644 index 0000000..ef1ead6 --- /dev/null +++ b/tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_size_big_endian.rs @@ -0,0 +1,131 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: Vec<u16>, +} +impl Foo { + pub fn a(&self) -> &Vec<u16> { + &self.a + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 5 + self.a.len() * 2 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.a.len() > 0xff_ffff_ffff_usize { + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "a", + count: self.a.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); + } + buf.put_uint(self.a.len() as u64, 5); + for elem in &self.a { + buf.put_u16(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 5, + got: buf.remaining(), + }); + } + let a_count = buf.get_uint(5) as usize; + if buf.remaining() < a_count * 2usize { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: a_count * 2usize, + got: buf.remaining(), + }); + } + let a = (0..a_count) + .map(|_| Ok::<_, DecodeError>(buf.get_u16())) + .collect::<Result<Vec<_>, DecodeError>>()?; + Ok((Self { a }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: Vec<Foo>, +} +impl Bar { + pub fn x(&self) -> &Vec<Foo> { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 5 + self.x.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + let x_size = self.x.iter().map(Packet::encoded_len).sum::<usize>(); + if x_size > 0xff_ffff_ffff_usize { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_size, + maximum_size: 0xff_ffff_ffff_usize, + }); + } + buf.put_uint(x_size as u64, 5); + for elem in &self.x { + elem.encode(buf)?; + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 5, + got: buf.remaining(), + }); + } + let x_size = buf.get_uint(5) as usize; + if buf.remaining() < x_size { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: x_size, + got: buf.remaining(), + }); + } + let (mut head, tail) = buf.split_at(x_size); + buf = tail; + let mut x = Vec::new(); + while !head.is_empty() { + x.push(Foo::decode_mut(&mut head)?); + } + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_size_little_endian.rs b/tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_size_little_endian.rs new file mode 100644 index 0000000..91381c5 --- /dev/null +++ b/tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_size_little_endian.rs @@ -0,0 +1,131 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: Vec<u16>, +} +impl Foo { + pub fn a(&self) -> &Vec<u16> { + &self.a + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 5 + self.a.len() * 2 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.a.len() > 0xff_ffff_ffff_usize { + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "a", + count: self.a.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); + } + buf.put_uint_le(self.a.len() as u64, 5); + for elem in &self.a { + buf.put_u16_le(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 5, + got: buf.remaining(), + }); + } + let a_count = buf.get_uint_le(5) as usize; + if buf.remaining() < a_count * 2usize { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: a_count * 2usize, + got: buf.remaining(), + }); + } + let a = (0..a_count) + .map(|_| Ok::<_, DecodeError>(buf.get_u16_le())) + .collect::<Result<Vec<_>, DecodeError>>()?; + Ok((Self { a }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: Vec<Foo>, +} +impl Bar { + pub fn x(&self) -> &Vec<Foo> { + &self.x + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 5 + self.x.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + let x_size = self.x.iter().map(Packet::encoded_len).sum::<usize>(); + if x_size > 0xff_ffff_ffff_usize { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_size, + maximum_size: 0xff_ffff_ffff_usize, + }); + } + buf.put_uint_le(x_size as u64, 5); + for elem in &self.x { + elem.encode(buf)?; + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 5, + got: buf.remaining(), + }); + } + let x_size = buf.get_uint_le(5) as usize; + if buf.remaining() < x_size { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: x_size, + got: buf.remaining(), + }); + } + let (mut head, tail) = buf.split_at(x_size); + buf = tail; + let mut x = Vec::new(); + while !head.is_empty() { + x.push(Foo::decode_mut(&mut head)?); + } + Ok((Self { x }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_with_padding_big_endian.rs b/tests/generated/rust/packet_decl_array_with_padding_big_endian.rs new file mode 100644 index 0000000..44d3643 --- /dev/null +++ b/tests/generated/rust/packet_decl_array_with_padding_big_endian.rs @@ -0,0 +1,123 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: Vec<u16>, +} +impl Foo { + pub fn a(&self) -> &Vec<u16> { + &self.a + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 5 + self.a.len() * 2 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.a.len() > 0xff_ffff_ffff_usize { + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "a", + count: self.a.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); + } + buf.put_uint(self.a.len() as u64, 5); + for elem in &self.a { + buf.put_u16(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 5, + got: buf.remaining(), + }); + } + let a_count = buf.get_uint(5) as usize; + if buf.remaining() < a_count * 2usize { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: a_count * 2usize, + got: buf.remaining(), + }); + } + let a = (0..a_count) + .map(|_| Ok::<_, DecodeError>(buf.get_u16())) + .collect::<Result<Vec<_>, DecodeError>>()?; + Ok((Self { a }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub a: Vec<Foo>, +} +impl Bar { + pub fn a(&self) -> &Vec<Foo> { + &self.a + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + self.a.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + let array_size = self.a.iter().map(Packet::encoded_len).sum::<usize>(); + if array_size > 128usize { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "a", + size: array_size, + maximum_size: 128usize, + }); + } + for elem in &self.a { + elem.encode(buf)?; + } + buf.put_bytes(0, 128usize - array_size); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 128usize { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 128usize, + got: buf.remaining(), + }); + } + let (mut head, tail) = buf.split_at(128usize); + buf = tail; + let mut a = Vec::new(); + while !head.is_empty() { + a.push(Foo::decode_mut(&mut head)?); + } + Ok((Self { a }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_array_with_padding_little_endian.rs b/tests/generated/rust/packet_decl_array_with_padding_little_endian.rs new file mode 100644 index 0000000..9295e39 --- /dev/null +++ b/tests/generated/rust/packet_decl_array_with_padding_little_endian.rs @@ -0,0 +1,123 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: Vec<u16>, +} +impl Foo { + pub fn a(&self) -> &Vec<u16> { + &self.a + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 5 + self.a.len() * 2 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.a.len() > 0xff_ffff_ffff_usize { + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "a", + count: self.a.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); + } + buf.put_uint_le(self.a.len() as u64, 5); + for elem in &self.a { + buf.put_u16_le(*elem); + } + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 5, + got: buf.remaining(), + }); + } + let a_count = buf.get_uint_le(5) as usize; + if buf.remaining() < a_count * 2usize { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: a_count * 2usize, + got: buf.remaining(), + }); + } + let a = (0..a_count) + .map(|_| Ok::<_, DecodeError>(buf.get_u16_le())) + .collect::<Result<Vec<_>, DecodeError>>()?; + Ok((Self { a }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub a: Vec<Foo>, +} +impl Bar { + pub fn a(&self) -> &Vec<Foo> { + &self.a + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + self.a.iter().map(Packet::encoded_len).sum::<usize>() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + let array_size = self.a.iter().map(Packet::encoded_len).sum::<usize>(); + if array_size > 128usize { + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "a", + size: array_size, + maximum_size: 128usize, + }); + } + for elem in &self.a { + elem.encode(buf)?; + } + buf.put_bytes(0, 128usize - array_size); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 128usize { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 128usize, + got: buf.remaining(), + }); + } + let (mut head, tail) = buf.split_at(128usize); + buf = tail; + let mut a = Vec::new(); + while !head.is_empty() { + a.push(Foo::decode_mut(&mut head)?); + } + Ok((Self { a }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_child_packets_big_endian.rs b/tests/generated/rust/packet_decl_child_packets_big_endian.rs new file mode 100644 index 0000000..f319ed6 --- /dev/null +++ b/tests/generated/rust/packet_decl_child_packets_big_endian.rs @@ -0,0 +1,372 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u16", into = "u16"))] +pub enum Enum16 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u16> for Enum16 { + type Error = u16; + fn try_from(value: u16) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum16::A), + 0x2 => Ok(Enum16::B), + _ => Err(value), + } + } +} +impl From<&Enum16> for u16 { + fn from(value: &Enum16) -> Self { + match value { + Enum16::A => 0x1, + Enum16::B => 0x2, + } + } +} +impl From<Enum16> for u16 { + fn from(value: Enum16) -> Self { + (&value).into() + } +} +impl From<Enum16> for i32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for i64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u8, + pub b: Enum16, + pub payload: Vec<u8>, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum FooChild { + Bar(Bar), + Baz(Baz), + None, +} +impl Foo { + pub fn specialize(&self) -> Result<FooChild, DecodeError> { + Ok( + match (self.a, self.b) { + (100, _) => FooChild::Bar(self.try_into()?), + (_, Enum16::B) => FooChild::Baz(self.try_into()?), + _ => FooChild::None, + }, + ) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> Enum16 { + self.b + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 4 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16(u16::from(self.b())); + if self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(self.payload.len() as u8); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let a = buf.get_u8(); + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let b = Enum16::try_from(buf.get_u16()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "b", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + Ok((Self { payload, a, b }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: u8, + pub b: Enum16, +} +impl TryFrom<&Foo> for Bar { + type Error = DecodeError; + fn try_from(parent: &Foo) -> Result<Bar, Self::Error> { + Bar::decode_partial(&parent) + } +} +impl TryFrom<Foo> for Bar { + type Error = DecodeError; + fn try_from(parent: Foo) -> Result<Bar, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&Bar> for Foo { + type Error = EncodeError; + fn try_from(packet: &Bar) -> Result<Foo, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Foo { + a: 100, + b: packet.b, + payload, + }) + } +} +impl TryFrom<Bar> for Foo { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Foo, Self::Error> { + (&packet).try_into() + } +} +impl Bar { + fn decode_partial(parent: &Foo) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.a() != 100 { + return Err(DecodeError::InvalidFieldValue { + packet: "Bar", + field: "a", + expected: "100", + actual: format!("{:?}", parent.a()), + }); + } + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let x = buf.get_u8(); + if buf.is_empty() { + Ok(Self { x, b: parent.b }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.x()); + Ok(()) + } + pub fn x(&self) -> u8 { + self.x + } + pub fn b(&self) -> Enum16 { + self.b + } + pub fn a(&self) -> u8 { + 100 + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 5 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16(u16::from(self.b())); + if 1 > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: 1, + maximum_size: 0xff, + }); + } + buf.put_u8(1 as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Foo::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Baz { + pub y: u16, + pub a: u8, +} +impl TryFrom<&Foo> for Baz { + type Error = DecodeError; + fn try_from(parent: &Foo) -> Result<Baz, Self::Error> { + Baz::decode_partial(&parent) + } +} +impl TryFrom<Foo> for Baz { + type Error = DecodeError; + fn try_from(parent: Foo) -> Result<Baz, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&Baz> for Foo { + type Error = EncodeError; + fn try_from(packet: &Baz) -> Result<Foo, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Foo { + a: packet.a, + b: Enum16::B, + payload, + }) + } +} +impl TryFrom<Baz> for Foo { + type Error = EncodeError; + fn try_from(packet: Baz) -> Result<Foo, Self::Error> { + (&packet).try_into() + } +} +impl Baz { + fn decode_partial(parent: &Foo) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.b() != Enum16::B { + return Err(DecodeError::InvalidFieldValue { + packet: "Baz", + field: "b", + expected: "Enum16::B", + actual: format!("{:?}", parent.b()), + }); + } + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Baz", + wanted: 2, + got: buf.remaining(), + }); + } + let y = buf.get_u16(); + if buf.is_empty() { + Ok(Self { y, a: parent.a }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(self.y()); + Ok(()) + } + pub fn y(&self) -> u16 { + self.y + } + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> Enum16 { + Enum16::B + } +} +impl Packet for Baz { + fn encoded_len(&self) -> usize { + 6 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16(u16::from(self.b())); + if 2 > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: 2, + maximum_size: 0xff, + }); + } + buf.put_u8(2 as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Foo::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/generated/rust/packet_decl_child_packets_little_endian.rs b/tests/generated/rust/packet_decl_child_packets_little_endian.rs new file mode 100644 index 0000000..047c42a --- /dev/null +++ b/tests/generated/rust/packet_decl_child_packets_little_endian.rs @@ -0,0 +1,372 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u16", into = "u16"))] +pub enum Enum16 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u16> for Enum16 { + type Error = u16; + fn try_from(value: u16) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum16::A), + 0x2 => Ok(Enum16::B), + _ => Err(value), + } + } +} +impl From<&Enum16> for u16 { + fn from(value: &Enum16) -> Self { + match value { + Enum16::A => 0x1, + Enum16::B => 0x2, + } + } +} +impl From<Enum16> for u16 { + fn from(value: Enum16) -> Self { + (&value).into() + } +} +impl From<Enum16> for i32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for i64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u8, + pub b: Enum16, + pub payload: Vec<u8>, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum FooChild { + Bar(Bar), + Baz(Baz), + None, +} +impl Foo { + pub fn specialize(&self) -> Result<FooChild, DecodeError> { + Ok( + match (self.a, self.b) { + (100, _) => FooChild::Bar(self.try_into()?), + (_, Enum16::B) => FooChild::Baz(self.try_into()?), + _ => FooChild::None, + }, + ) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> Enum16 { + self.b + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 4 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16_le(u16::from(self.b())); + if self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(self.payload.len() as u8); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let a = buf.get_u8(); + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let b = Enum16::try_from(buf.get_u16_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "b", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + Ok((Self { payload, a, b }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: u8, + pub b: Enum16, +} +impl TryFrom<&Foo> for Bar { + type Error = DecodeError; + fn try_from(parent: &Foo) -> Result<Bar, Self::Error> { + Bar::decode_partial(&parent) + } +} +impl TryFrom<Foo> for Bar { + type Error = DecodeError; + fn try_from(parent: Foo) -> Result<Bar, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&Bar> for Foo { + type Error = EncodeError; + fn try_from(packet: &Bar) -> Result<Foo, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Foo { + a: 100, + b: packet.b, + payload, + }) + } +} +impl TryFrom<Bar> for Foo { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Foo, Self::Error> { + (&packet).try_into() + } +} +impl Bar { + fn decode_partial(parent: &Foo) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.a() != 100 { + return Err(DecodeError::InvalidFieldValue { + packet: "Bar", + field: "a", + expected: "100", + actual: format!("{:?}", parent.a()), + }); + } + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let x = buf.get_u8(); + if buf.is_empty() { + Ok(Self { x, b: parent.b }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.x()); + Ok(()) + } + pub fn x(&self) -> u8 { + self.x + } + pub fn b(&self) -> Enum16 { + self.b + } + pub fn a(&self) -> u8 { + 100 + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 5 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16_le(u16::from(self.b())); + if 1 > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: 1, + maximum_size: 0xff, + }); + } + buf.put_u8(1 as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Foo::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Baz { + pub y: u16, + pub a: u8, +} +impl TryFrom<&Foo> for Baz { + type Error = DecodeError; + fn try_from(parent: &Foo) -> Result<Baz, Self::Error> { + Baz::decode_partial(&parent) + } +} +impl TryFrom<Foo> for Baz { + type Error = DecodeError; + fn try_from(parent: Foo) -> Result<Baz, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&Baz> for Foo { + type Error = EncodeError; + fn try_from(packet: &Baz) -> Result<Foo, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Foo { + a: packet.a, + b: Enum16::B, + payload, + }) + } +} +impl TryFrom<Baz> for Foo { + type Error = EncodeError; + fn try_from(packet: Baz) -> Result<Foo, Self::Error> { + (&packet).try_into() + } +} +impl Baz { + fn decode_partial(parent: &Foo) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.b() != Enum16::B { + return Err(DecodeError::InvalidFieldValue { + packet: "Baz", + field: "b", + expected: "Enum16::B", + actual: format!("{:?}", parent.b()), + }); + } + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Baz", + wanted: 2, + got: buf.remaining(), + }); + } + let y = buf.get_u16_le(); + if buf.is_empty() { + Ok(Self { y, a: parent.a }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(self.y()); + Ok(()) + } + pub fn y(&self) -> u16 { + self.y + } + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> Enum16 { + Enum16::B + } +} +impl Packet for Baz { + fn encoded_len(&self) -> usize { + 6 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16_le(u16::from(self.b())); + if 2 > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: 2, + maximum_size: 0xff, + }); + } + buf.put_u8(2 as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Foo::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/generated/rust/packet_decl_complex_scalars_big_endian.rs b/tests/generated/rust/packet_decl_complex_scalars_big_endian.rs new file mode 100644 index 0000000..e2f6e8c --- /dev/null +++ b/tests/generated/rust/packet_decl_complex_scalars_big_endian.rs @@ -0,0 +1,141 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u8, + pub b: u8, + pub c: u8, + pub d: u32, + pub e: u16, + pub f: u8, +} +impl Foo { + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> u8 { + self.b + } + pub fn c(&self) -> u8 { + self.c + } + pub fn d(&self) -> u32 { + self.d + } + pub fn e(&self) -> u16 { + self.e + } + pub fn f(&self) -> u8 { + self.f + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 7 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.a() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a() as u64, + maximum_value: 0x7 as u64, + }); + } + if self.c() > 0x1f { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "c", + value: self.c() as u64, + maximum_value: 0x1f as u64, + }); + } + let value = (self.a() as u16) | ((self.b() as u16) << 3) + | ((self.c() as u16) << 11); + buf.put_u16(value); + if self.d() > 0xff_ffff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "d", + value: self.d() as u64, + maximum_value: 0xff_ffff as u64, + }); + } + buf.put_uint(self.d() as u64, 3); + if self.e() > 0xfff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "e", + value: self.e() as u64, + maximum_value: 0xfff as u64, + }); + } + if self.f() > 0xf { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "f", + value: self.f() as u64, + maximum_value: 0xf as u64, + }); + } + let value = self.e() | ((self.f() as u16) << 12); + buf.put_u16(value); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let chunk = buf.get_u16(); + let a = (chunk & 0x7) as u8; + let b = (chunk >> 3) as u8; + let c = ((chunk >> 11) & 0x1f) as u8; + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let d = buf.get_uint(3) as u32; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let chunk = buf.get_u16(); + let e = (chunk & 0xfff); + let f = ((chunk >> 12) & 0xf) as u8; + Ok((Self { a, b, c, d, e, f }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_complex_scalars_little_endian.rs b/tests/generated/rust/packet_decl_complex_scalars_little_endian.rs new file mode 100644 index 0000000..b18d238 --- /dev/null +++ b/tests/generated/rust/packet_decl_complex_scalars_little_endian.rs @@ -0,0 +1,141 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u8, + pub b: u8, + pub c: u8, + pub d: u32, + pub e: u16, + pub f: u8, +} +impl Foo { + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> u8 { + self.b + } + pub fn c(&self) -> u8 { + self.c + } + pub fn d(&self) -> u32 { + self.d + } + pub fn e(&self) -> u16 { + self.e + } + pub fn f(&self) -> u8 { + self.f + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 7 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.a() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a() as u64, + maximum_value: 0x7 as u64, + }); + } + if self.c() > 0x1f { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "c", + value: self.c() as u64, + maximum_value: 0x1f as u64, + }); + } + let value = (self.a() as u16) | ((self.b() as u16) << 3) + | ((self.c() as u16) << 11); + buf.put_u16_le(value); + if self.d() > 0xff_ffff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "d", + value: self.d() as u64, + maximum_value: 0xff_ffff as u64, + }); + } + buf.put_uint_le(self.d() as u64, 3); + if self.e() > 0xfff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "e", + value: self.e() as u64, + maximum_value: 0xfff as u64, + }); + } + if self.f() > 0xf { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "f", + value: self.f() as u64, + maximum_value: 0xf as u64, + }); + } + let value = self.e() | ((self.f() as u16) << 12); + buf.put_u16_le(value); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let chunk = buf.get_u16_le(); + let a = (chunk & 0x7) as u8; + let b = (chunk >> 3) as u8; + let c = ((chunk >> 11) & 0x1f) as u8; + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let d = buf.get_uint_le(3) as u32; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let chunk = buf.get_u16_le(); + let e = (chunk & 0xfff); + let f = ((chunk >> 12) & 0xf) as u8; + Ok((Self { a, b, c, d, e, f }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_custom_field_big_endian.rs b/tests/generated/rust/packet_decl_custom_field_big_endian.rs new file mode 100644 index 0000000..fc9f02a --- /dev/null +++ b/tests/generated/rust/packet_decl_custom_field_big_endian.rs @@ -0,0 +1,131 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u32", into = "u32"))] +pub struct Bar1(u32); +impl From<&Bar1> for u32 { + fn from(value: &Bar1) -> u32 { + value.0 + } +} +impl From<Bar1> for u32 { + fn from(value: Bar1) -> u32 { + value.0 + } +} +impl Packet for Bar1 { + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.len() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar1", + wanted: 3, + got: buf.len(), + }); + } + Ok(((buf.get_uint(3) as u32).try_into().unwrap(), buf)) + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_uint(u32::from(self) as u64, 3); + Ok(()) + } + fn encoded_len(&self) -> usize { + 3 + } +} +impl TryFrom<u32> for Bar1 { + type Error = u32; + fn try_from(value: u32) -> Result<Self, Self::Error> { + if value > 0xff_ffff { Err(value) } else { Ok(Bar1(value)) } + } +} +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(from = "u32", into = "u32"))] +pub struct Bar2(u32); +impl From<&Bar2> for u32 { + fn from(value: &Bar2) -> u32 { + value.0 + } +} +impl From<Bar2> for u32 { + fn from(value: Bar2) -> u32 { + value.0 + } +} +impl Packet for Bar2 { + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.len() < 4 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar2", + wanted: 4, + got: buf.len(), + }); + } + Ok((buf.get_u32().into(), buf)) + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u32(u32::from(self)); + Ok(()) + } + fn encoded_len(&self) -> usize { + 4 + } +} +impl From<u32> for Bar2 { + fn from(value: u32) -> Self { + Bar2(value) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: Bar1, + pub b: Bar2, +} +impl Foo { + pub fn a(&self) -> Bar1 { + self.a + } + pub fn b(&self) -> Bar2 { + self.b + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 56 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_uint(u32::from(self.a) as u64, 3); + buf.put_u32(u32::from(self.b)); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let a = (buf.get_uint(3) as u32).try_into().unwrap(); + let b = buf.get_u32().into(); + Ok((Self { a, b }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_custom_field_little_endian.rs b/tests/generated/rust/packet_decl_custom_field_little_endian.rs new file mode 100644 index 0000000..e48f67e --- /dev/null +++ b/tests/generated/rust/packet_decl_custom_field_little_endian.rs @@ -0,0 +1,131 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u32", into = "u32"))] +pub struct Bar1(u32); +impl From<&Bar1> for u32 { + fn from(value: &Bar1) -> u32 { + value.0 + } +} +impl From<Bar1> for u32 { + fn from(value: Bar1) -> u32 { + value.0 + } +} +impl Packet for Bar1 { + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.len() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar1", + wanted: 3, + got: buf.len(), + }); + } + Ok(((buf.get_uint_le(3) as u32).try_into().unwrap(), buf)) + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_uint_le(u32::from(self) as u64, 3); + Ok(()) + } + fn encoded_len(&self) -> usize { + 3 + } +} +impl TryFrom<u32> for Bar1 { + type Error = u32; + fn try_from(value: u32) -> Result<Self, Self::Error> { + if value > 0xff_ffff { Err(value) } else { Ok(Bar1(value)) } + } +} +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(from = "u32", into = "u32"))] +pub struct Bar2(u32); +impl From<&Bar2> for u32 { + fn from(value: &Bar2) -> u32 { + value.0 + } +} +impl From<Bar2> for u32 { + fn from(value: Bar2) -> u32 { + value.0 + } +} +impl Packet for Bar2 { + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.len() < 4 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar2", + wanted: 4, + got: buf.len(), + }); + } + Ok((buf.get_u32_le().into(), buf)) + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u32_le(u32::from(self)); + Ok(()) + } + fn encoded_len(&self) -> usize { + 4 + } +} +impl From<u32> for Bar2 { + fn from(value: u32) -> Self { + Bar2(value) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: Bar1, + pub b: Bar2, +} +impl Foo { + pub fn a(&self) -> Bar1 { + self.a + } + pub fn b(&self) -> Bar2 { + self.b + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 56 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_uint_le(u32::from(self.a) as u64, 3); + buf.put_u32_le(u32::from(self.b)); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let a = (buf.get_uint_le(3) as u32).try_into().unwrap(); + let b = buf.get_u32_le().into(); + Ok((Self { a, b }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_empty_big_endian.rs b/tests/generated/rust/packet_decl_empty_big_endian.rs new file mode 100644 index 0000000..64c4adf --- /dev/null +++ b/tests/generated/rust/packet_decl_empty_big_endian.rs @@ -0,0 +1,40 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo {} +impl Foo {} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 0 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + Ok((Self {}, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_empty_little_endian.rs b/tests/generated/rust/packet_decl_empty_little_endian.rs new file mode 100644 index 0000000..64c4adf --- /dev/null +++ b/tests/generated/rust/packet_decl_empty_little_endian.rs @@ -0,0 +1,40 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo {} +impl Foo {} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 0 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + Ok((Self {}, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_fixed_enum_field_big_endian.rs b/tests/generated/rust/packet_decl_fixed_enum_field_big_endian.rs new file mode 100644 index 0000000..62b8e7f --- /dev/null +++ b/tests/generated/rust/packet_decl_fixed_enum_field_big_endian.rs @@ -0,0 +1,138 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[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 Enum7 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u8> for Enum7 { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum7::A), + 0x2 => Ok(Enum7::B), + _ => Err(value), + } + } +} +impl From<&Enum7> for u8 { + fn from(value: &Enum7) -> Self { + match value { + Enum7::A => 0x1, + Enum7::B => 0x2, + } + } +} +impl From<Enum7> for u8 { + fn from(value: Enum7) -> Self { + (&value).into() + } +} +impl From<Enum7> for i8 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for i16 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for i32 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for i64 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for u16 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for u32 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for u64 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub b: u64, +} +impl Foo { + pub fn b(&self) -> u64 { + self.b + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 8 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.b() > 0x1ff_ffff_ffff_ffff_u64 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "b", + value: self.b() as u64, + maximum_value: 0x1ff_ffff_ffff_ffff_u64 as u64, + }); + } + let value = (u8::from(Enum7::A) as u64) | (self.b() << 7); + buf.put_u64(value); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 8 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 8, + got: buf.remaining(), + }); + } + let chunk = buf.get_u64(); + let fixed_value = (chunk & 0x7f) as u8; + if fixed_value != u8::from(Enum7::A) { + return Err(DecodeError::InvalidFixedValue { + expected: u8::from(Enum7::A) as u64, + actual: fixed_value as u64, + }); + } + let b = ((chunk >> 7) & 0x1ff_ffff_ffff_ffff_u64); + Ok((Self { b }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_fixed_enum_field_little_endian.rs b/tests/generated/rust/packet_decl_fixed_enum_field_little_endian.rs new file mode 100644 index 0000000..015edf7 --- /dev/null +++ b/tests/generated/rust/packet_decl_fixed_enum_field_little_endian.rs @@ -0,0 +1,138 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[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 Enum7 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u8> for Enum7 { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum7::A), + 0x2 => Ok(Enum7::B), + _ => Err(value), + } + } +} +impl From<&Enum7> for u8 { + fn from(value: &Enum7) -> Self { + match value { + Enum7::A => 0x1, + Enum7::B => 0x2, + } + } +} +impl From<Enum7> for u8 { + fn from(value: Enum7) -> Self { + (&value).into() + } +} +impl From<Enum7> for i8 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for i16 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for i32 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for i64 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for u16 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for u32 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for u64 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub b: u64, +} +impl Foo { + pub fn b(&self) -> u64 { + self.b + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 8 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.b() > 0x1ff_ffff_ffff_ffff_u64 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "b", + value: self.b() as u64, + maximum_value: 0x1ff_ffff_ffff_ffff_u64 as u64, + }); + } + let value = (u8::from(Enum7::A) as u64) | (self.b() << 7); + buf.put_u64_le(value); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 8 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 8, + got: buf.remaining(), + }); + } + let chunk = buf.get_u64_le(); + let fixed_value = (chunk & 0x7f) as u8; + if fixed_value != u8::from(Enum7::A) { + return Err(DecodeError::InvalidFixedValue { + expected: u8::from(Enum7::A) as u64, + actual: fixed_value as u64, + }); + } + let b = ((chunk >> 7) & 0x1ff_ffff_ffff_ffff_u64); + Ok((Self { b }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_fixed_scalar_field_big_endian.rs b/tests/generated/rust/packet_decl_fixed_scalar_field_big_endian.rs new file mode 100644 index 0000000..c63be93 --- /dev/null +++ b/tests/generated/rust/packet_decl_fixed_scalar_field_big_endian.rs @@ -0,0 +1,72 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub b: u64, +} +impl Foo { + pub fn b(&self) -> u64 { + self.b + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 8 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.b() > 0x1ff_ffff_ffff_ffff_u64 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "b", + value: self.b() as u64, + maximum_value: 0x1ff_ffff_ffff_ffff_u64 as u64, + }); + } + let value = (7 as u64) | (self.b() << 7); + buf.put_u64(value); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 8 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 8, + got: buf.remaining(), + }); + } + let chunk = buf.get_u64(); + let fixed_value = (chunk & 0x7f) as u8; + if fixed_value != 7 { + return Err(DecodeError::InvalidFixedValue { + expected: 7, + actual: fixed_value as u64, + }); + } + let b = ((chunk >> 7) & 0x1ff_ffff_ffff_ffff_u64); + Ok((Self { b }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_fixed_scalar_field_little_endian.rs b/tests/generated/rust/packet_decl_fixed_scalar_field_little_endian.rs new file mode 100644 index 0000000..a6c4366 --- /dev/null +++ b/tests/generated/rust/packet_decl_fixed_scalar_field_little_endian.rs @@ -0,0 +1,72 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub b: u64, +} +impl Foo { + pub fn b(&self) -> u64 { + self.b + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 8 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.b() > 0x1ff_ffff_ffff_ffff_u64 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "b", + value: self.b() as u64, + maximum_value: 0x1ff_ffff_ffff_ffff_u64 as u64, + }); + } + let value = (7 as u64) | (self.b() << 7); + buf.put_u64_le(value); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 8 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 8, + got: buf.remaining(), + }); + } + let chunk = buf.get_u64_le(); + let fixed_value = (chunk & 0x7f) as u8; + if fixed_value != 7 { + return Err(DecodeError::InvalidFixedValue { + expected: 7, + actual: fixed_value as u64, + }); + } + let b = ((chunk >> 7) & 0x1ff_ffff_ffff_ffff_u64); + Ok((Self { b }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_grand_children_big_endian.rs b/tests/generated/rust/packet_decl_grand_children_big_endian.rs new file mode 100644 index 0000000..ceab016 --- /dev/null +++ b/tests/generated/rust/packet_decl_grand_children_big_endian.rs @@ -0,0 +1,594 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u16", into = "u16"))] +pub enum Enum16 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u16> for Enum16 { + type Error = u16; + fn try_from(value: u16) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum16::A), + 0x2 => Ok(Enum16::B), + _ => Err(value), + } + } +} +impl From<&Enum16> for u16 { + fn from(value: &Enum16) -> Self { + match value { + Enum16::A => 0x1, + Enum16::B => 0x2, + } + } +} +impl From<Enum16> for u16 { + fn from(value: Enum16) -> Self { + (&value).into() + } +} +impl From<Enum16> for i32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for i64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Parent { + pub foo: Enum16, + pub bar: Enum16, + pub baz: Enum16, + pub payload: Vec<u8>, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ParentChild { + Child(Child), + None, +} +impl Parent { + pub fn specialize(&self) -> Result<ParentChild, DecodeError> { + Ok( + match (self.foo,) { + (Enum16::A,) => ParentChild::Child(self.try_into()?), + _ => ParentChild::None, + }, + ) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn foo(&self) -> Enum16 { + self.foo + } + pub fn bar(&self) -> Enum16 { + self.bar + } + pub fn baz(&self) -> Enum16 { + self.baz + } +} +impl Packet for Parent { + fn encoded_len(&self) -> usize { + 7 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(u16::from(self.foo())); + buf.put_u16(u16::from(self.bar())); + buf.put_u16(u16::from(self.baz())); + if self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(self.payload.len() as u8); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let foo = Enum16::try_from(buf.get_u16()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "foo", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let bar = Enum16::try_from(buf.get_u16()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "bar", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let baz = Enum16::try_from(buf.get_u16()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "baz", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + Ok((Self { payload, foo, bar, baz }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Child { + pub quux: Enum16, + pub bar: Enum16, + pub baz: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Parent> for Child { + type Error = DecodeError; + fn try_from(parent: &Parent) -> Result<Child, Self::Error> { + Child::decode_partial(&parent) + } +} +impl TryFrom<Parent> for Child { + type Error = DecodeError; + fn try_from(parent: Parent) -> Result<Child, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&Child> for Parent { + type Error = EncodeError; + fn try_from(packet: &Child) -> Result<Parent, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Parent { + foo: Enum16::A, + bar: packet.bar, + baz: packet.baz, + payload, + }) + } +} +impl TryFrom<Child> for Parent { + type Error = EncodeError; + fn try_from(packet: Child) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ChildChild { + GrandChild(GrandChild), + None, +} +impl Child { + pub fn specialize(&self) -> Result<ChildChild, DecodeError> { + Ok( + match (self.bar, self.quux) { + (Enum16::A, Enum16::A) => ChildChild::GrandChild(self.try_into()?), + _ => ChildChild::None, + }, + ) + } + fn decode_partial(parent: &Parent) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.foo() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "Child", + field: "foo", + expected: "Enum16::A", + actual: format!("{:?}", parent.foo()), + }); + } + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Child", + wanted: 2, + got: buf.remaining(), + }); + } + let quux = Enum16::try_from(buf.get_u16()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Child", + field: "quux", + value: unknown_val as u64, + type_: "Enum16", + })?; + let payload = buf.to_vec(); + buf.advance(payload.len()); + if buf.is_empty() { + Ok(Self { + payload, + quux, + bar: parent.bar, + baz: parent.baz, + }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(u16::from(self.quux())); + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn quux(&self) -> Enum16 { + self.quux + } + pub fn bar(&self) -> Enum16 { + self.bar + } + pub fn baz(&self) -> Enum16 { + self.baz + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for Child { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(u16::from(self.foo())); + buf.put_u16(u16::from(self.bar())); + buf.put_u16(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Parent::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GrandChild { + pub baz: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Child> for GrandChild { + type Error = DecodeError; + fn try_from(parent: &Child) -> Result<GrandChild, Self::Error> { + GrandChild::decode_partial(&parent) + } +} +impl TryFrom<Child> for GrandChild { + type Error = DecodeError; + fn try_from(parent: Child) -> Result<GrandChild, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&GrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Child, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Child { + quux: Enum16::A, + bar: Enum16::A, + baz: packet.baz, + payload, + }) + } +} +impl TryFrom<GrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: GrandChild) -> Result<Child, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&GrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Parent, Self::Error> { + (&Child::try_from(packet)?).try_into() + } +} +impl TryFrom<GrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: GrandChild) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum GrandChildChild { + GrandGrandChild(GrandGrandChild), + None, +} +impl GrandChild { + pub fn specialize(&self) -> Result<GrandChildChild, DecodeError> { + Ok( + match (self.baz,) { + (Enum16::A,) => GrandChildChild::GrandGrandChild(self.try_into()?), + _ => GrandChildChild::None, + }, + ) + } + fn decode_partial(parent: &Child) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.bar() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "GrandChild", + field: "bar", + expected: "Enum16::A", + actual: format!("{:?}", parent.bar()), + }); + } + if parent.quux() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "GrandChild", + field: "quux", + expected: "Enum16::A", + actual: format!("{:?}", parent.quux()), + }); + } + let payload = buf.to_vec(); + buf.advance(payload.len()); + if buf.is_empty() { + Ok(Self { payload, baz: parent.baz }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn baz(&self) -> Enum16 { + self.baz + } + pub fn quux(&self) -> Enum16 { + Enum16::A + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } + pub fn bar(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for GrandChild { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(u16::from(self.foo())); + buf.put_u16(u16::from(self.bar())); + buf.put_u16(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + buf.put_u16(u16::from(self.quux())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Child::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GrandGrandChild { + pub payload: Vec<u8>, +} +impl TryFrom<&GrandChild> for GrandGrandChild { + type Error = DecodeError; + fn try_from(parent: &GrandChild) -> Result<GrandGrandChild, Self::Error> { + GrandGrandChild::decode_partial(&parent) + } +} +impl TryFrom<GrandChild> for GrandGrandChild { + type Error = DecodeError; + fn try_from(parent: GrandChild) -> Result<GrandGrandChild, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&GrandGrandChild> for GrandChild { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<GrandChild, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(GrandChild { + baz: Enum16::A, + payload, + }) + } +} +impl TryFrom<GrandGrandChild> for GrandChild { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<GrandChild, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&GrandGrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Child, Self::Error> { + (&GrandChild::try_from(packet)?).try_into() + } +} +impl TryFrom<GrandGrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<Child, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&GrandGrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Parent, Self::Error> { + (&GrandChild::try_from(packet)?).try_into() + } +} +impl TryFrom<GrandGrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +impl GrandGrandChild { + fn decode_partial(parent: &GrandChild) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.baz() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "GrandGrandChild", + field: "baz", + expected: "Enum16::A", + actual: format!("{:?}", parent.baz()), + }); + } + let payload = buf.to_vec(); + buf.advance(payload.len()); + if buf.is_empty() { + Ok(Self { payload }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn quux(&self) -> Enum16 { + Enum16::A + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } + pub fn bar(&self) -> Enum16 { + Enum16::A + } + pub fn baz(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for GrandGrandChild { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(u16::from(self.foo())); + buf.put_u16(u16::from(self.bar())); + buf.put_u16(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + buf.put_u16(u16::from(self.quux())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = GrandChild::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/generated/rust/packet_decl_grand_children_little_endian.rs b/tests/generated/rust/packet_decl_grand_children_little_endian.rs new file mode 100644 index 0000000..48ddd7b --- /dev/null +++ b/tests/generated/rust/packet_decl_grand_children_little_endian.rs @@ -0,0 +1,594 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u16", into = "u16"))] +pub enum Enum16 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u16> for Enum16 { + type Error = u16; + fn try_from(value: u16) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum16::A), + 0x2 => Ok(Enum16::B), + _ => Err(value), + } + } +} +impl From<&Enum16> for u16 { + fn from(value: &Enum16) -> Self { + match value { + Enum16::A => 0x1, + Enum16::B => 0x2, + } + } +} +impl From<Enum16> for u16 { + fn from(value: Enum16) -> Self { + (&value).into() + } +} +impl From<Enum16> for i32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for i64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Parent { + pub foo: Enum16, + pub bar: Enum16, + pub baz: Enum16, + pub payload: Vec<u8>, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ParentChild { + Child(Child), + None, +} +impl Parent { + pub fn specialize(&self) -> Result<ParentChild, DecodeError> { + Ok( + match (self.foo,) { + (Enum16::A,) => ParentChild::Child(self.try_into()?), + _ => ParentChild::None, + }, + ) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn foo(&self) -> Enum16 { + self.foo + } + pub fn bar(&self) -> Enum16 { + self.bar + } + pub fn baz(&self) -> Enum16 { + self.baz + } +} +impl Packet for Parent { + fn encoded_len(&self) -> usize { + 7 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(u16::from(self.foo())); + buf.put_u16_le(u16::from(self.bar())); + buf.put_u16_le(u16::from(self.baz())); + if self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(self.payload.len() as u8); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let foo = Enum16::try_from(buf.get_u16_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "foo", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let bar = Enum16::try_from(buf.get_u16_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "bar", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let baz = Enum16::try_from(buf.get_u16_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "baz", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + Ok((Self { payload, foo, bar, baz }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Child { + pub quux: Enum16, + pub bar: Enum16, + pub baz: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Parent> for Child { + type Error = DecodeError; + fn try_from(parent: &Parent) -> Result<Child, Self::Error> { + Child::decode_partial(&parent) + } +} +impl TryFrom<Parent> for Child { + type Error = DecodeError; + fn try_from(parent: Parent) -> Result<Child, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&Child> for Parent { + type Error = EncodeError; + fn try_from(packet: &Child) -> Result<Parent, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Parent { + foo: Enum16::A, + bar: packet.bar, + baz: packet.baz, + payload, + }) + } +} +impl TryFrom<Child> for Parent { + type Error = EncodeError; + fn try_from(packet: Child) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ChildChild { + GrandChild(GrandChild), + None, +} +impl Child { + pub fn specialize(&self) -> Result<ChildChild, DecodeError> { + Ok( + match (self.bar, self.quux) { + (Enum16::A, Enum16::A) => ChildChild::GrandChild(self.try_into()?), + _ => ChildChild::None, + }, + ) + } + fn decode_partial(parent: &Parent) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.foo() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "Child", + field: "foo", + expected: "Enum16::A", + actual: format!("{:?}", parent.foo()), + }); + } + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Child", + wanted: 2, + got: buf.remaining(), + }); + } + let quux = Enum16::try_from(buf.get_u16_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Child", + field: "quux", + value: unknown_val as u64, + type_: "Enum16", + })?; + let payload = buf.to_vec(); + buf.advance(payload.len()); + if buf.is_empty() { + Ok(Self { + payload, + quux, + bar: parent.bar, + baz: parent.baz, + }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(u16::from(self.quux())); + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn quux(&self) -> Enum16 { + self.quux + } + pub fn bar(&self) -> Enum16 { + self.bar + } + pub fn baz(&self) -> Enum16 { + self.baz + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for Child { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(u16::from(self.foo())); + buf.put_u16_le(u16::from(self.bar())); + buf.put_u16_le(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Parent::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GrandChild { + pub baz: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Child> for GrandChild { + type Error = DecodeError; + fn try_from(parent: &Child) -> Result<GrandChild, Self::Error> { + GrandChild::decode_partial(&parent) + } +} +impl TryFrom<Child> for GrandChild { + type Error = DecodeError; + fn try_from(parent: Child) -> Result<GrandChild, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&GrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Child, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Child { + quux: Enum16::A, + bar: Enum16::A, + baz: packet.baz, + payload, + }) + } +} +impl TryFrom<GrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: GrandChild) -> Result<Child, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&GrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Parent, Self::Error> { + (&Child::try_from(packet)?).try_into() + } +} +impl TryFrom<GrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: GrandChild) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum GrandChildChild { + GrandGrandChild(GrandGrandChild), + None, +} +impl GrandChild { + pub fn specialize(&self) -> Result<GrandChildChild, DecodeError> { + Ok( + match (self.baz,) { + (Enum16::A,) => GrandChildChild::GrandGrandChild(self.try_into()?), + _ => GrandChildChild::None, + }, + ) + } + fn decode_partial(parent: &Child) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.bar() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "GrandChild", + field: "bar", + expected: "Enum16::A", + actual: format!("{:?}", parent.bar()), + }); + } + if parent.quux() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "GrandChild", + field: "quux", + expected: "Enum16::A", + actual: format!("{:?}", parent.quux()), + }); + } + let payload = buf.to_vec(); + buf.advance(payload.len()); + if buf.is_empty() { + Ok(Self { payload, baz: parent.baz }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn baz(&self) -> Enum16 { + self.baz + } + pub fn quux(&self) -> Enum16 { + Enum16::A + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } + pub fn bar(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for GrandChild { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(u16::from(self.foo())); + buf.put_u16_le(u16::from(self.bar())); + buf.put_u16_le(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + buf.put_u16_le(u16::from(self.quux())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Child::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GrandGrandChild { + pub payload: Vec<u8>, +} +impl TryFrom<&GrandChild> for GrandGrandChild { + type Error = DecodeError; + fn try_from(parent: &GrandChild) -> Result<GrandGrandChild, Self::Error> { + GrandGrandChild::decode_partial(&parent) + } +} +impl TryFrom<GrandChild> for GrandGrandChild { + type Error = DecodeError; + fn try_from(parent: GrandChild) -> Result<GrandGrandChild, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&GrandGrandChild> for GrandChild { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<GrandChild, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(GrandChild { + baz: Enum16::A, + payload, + }) + } +} +impl TryFrom<GrandGrandChild> for GrandChild { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<GrandChild, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&GrandGrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Child, Self::Error> { + (&GrandChild::try_from(packet)?).try_into() + } +} +impl TryFrom<GrandGrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<Child, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&GrandGrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Parent, Self::Error> { + (&GrandChild::try_from(packet)?).try_into() + } +} +impl TryFrom<GrandGrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +impl GrandGrandChild { + fn decode_partial(parent: &GrandChild) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.baz() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "GrandGrandChild", + field: "baz", + expected: "Enum16::A", + actual: format!("{:?}", parent.baz()), + }); + } + let payload = buf.to_vec(); + buf.advance(payload.len()); + if buf.is_empty() { + Ok(Self { payload }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn quux(&self) -> Enum16 { + Enum16::A + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } + pub fn bar(&self) -> Enum16 { + Enum16::A + } + pub fn baz(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for GrandGrandChild { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(u16::from(self.foo())); + buf.put_u16_le(u16::from(self.bar())); + buf.put_u16_le(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + buf.put_u16_le(u16::from(self.quux())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = GrandChild::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/generated/rust/packet_decl_mask_scalar_value_big_endian.rs b/tests/generated/rust/packet_decl_mask_scalar_value_big_endian.rs new file mode 100644 index 0000000..9ed566f --- /dev/null +++ b/tests/generated/rust/packet_decl_mask_scalar_value_big_endian.rs @@ -0,0 +1,91 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u8, + pub b: u32, + pub c: u8, +} +impl Foo { + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> u32 { + self.b + } + pub fn c(&self) -> u8 { + self.c + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 4 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.a() > 0x3 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a() as u64, + maximum_value: 0x3 as u64, + }); + } + if self.b() > 0xff_ffff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "b", + value: self.b() as u64, + maximum_value: 0xff_ffff as u64, + }); + } + if self.c() > 0x3f { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "c", + value: self.c() as u64, + maximum_value: 0x3f as u64, + }); + } + let value = (self.a() as u32) | (self.b() << 2) | ((self.c() as u32) << 26); + buf.put_u32(value); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 4 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 4, + got: buf.remaining(), + }); + } + let chunk = buf.get_u32(); + let a = (chunk & 0x3) as u8; + let b = ((chunk >> 2) & 0xff_ffff); + let c = ((chunk >> 26) & 0x3f) as u8; + Ok((Self { a, b, c }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_mask_scalar_value_little_endian.rs b/tests/generated/rust/packet_decl_mask_scalar_value_little_endian.rs new file mode 100644 index 0000000..da4bb64 --- /dev/null +++ b/tests/generated/rust/packet_decl_mask_scalar_value_little_endian.rs @@ -0,0 +1,91 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u8, + pub b: u32, + pub c: u8, +} +impl Foo { + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> u32 { + self.b + } + pub fn c(&self) -> u8 { + self.c + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 4 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.a() > 0x3 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a() as u64, + maximum_value: 0x3 as u64, + }); + } + if self.b() > 0xff_ffff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "b", + value: self.b() as u64, + maximum_value: 0xff_ffff as u64, + }); + } + if self.c() > 0x3f { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "c", + value: self.c() as u64, + maximum_value: 0x3f as u64, + }); + } + let value = (self.a() as u32) | (self.b() << 2) | ((self.c() as u32) << 26); + buf.put_u32_le(value); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 4 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 4, + got: buf.remaining(), + }); + } + let chunk = buf.get_u32_le(); + let a = (chunk & 0x3) as u8; + let b = ((chunk >> 2) & 0xff_ffff); + let c = ((chunk >> 26) & 0x3f) as u8; + Ok((Self { a, b, c }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_mixed_scalars_enums_big_endian.rs b/tests/generated/rust/packet_decl_mixed_scalars_enums_big_endian.rs new file mode 100644 index 0000000..a974b70 --- /dev/null +++ b/tests/generated/rust/packet_decl_mixed_scalars_enums_big_endian.rs @@ -0,0 +1,223 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[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 Enum7 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u8> for Enum7 { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum7::A), + 0x2 => Ok(Enum7::B), + _ => Err(value), + } + } +} +impl From<&Enum7> for u8 { + fn from(value: &Enum7) -> Self { + match value { + Enum7::A => 0x1, + Enum7::B => 0x2, + } + } +} +impl From<Enum7> for u8 { + fn from(value: Enum7) -> Self { + (&value).into() + } +} +impl From<Enum7> for i8 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for i16 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for i32 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for i64 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for u16 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for u32 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for u64 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u16", into = "u16"))] +pub enum Enum9 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u16> for Enum9 { + type Error = u16; + fn try_from(value: u16) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum9::A), + 0x2 => Ok(Enum9::B), + _ => Err(value), + } + } +} +impl From<&Enum9> for u16 { + fn from(value: &Enum9) -> Self { + match value { + Enum9::A => 0x1, + Enum9::B => 0x2, + } + } +} +impl From<Enum9> for u16 { + fn from(value: Enum9) -> Self { + (&value).into() + } +} +impl From<Enum9> for i16 { + fn from(value: Enum9) -> Self { + u16::from(value) as Self + } +} +impl From<Enum9> for i32 { + fn from(value: Enum9) -> Self { + u16::from(value) as Self + } +} +impl From<Enum9> for i64 { + fn from(value: Enum9) -> Self { + u16::from(value) as Self + } +} +impl From<Enum9> for u32 { + fn from(value: Enum9) -> Self { + u16::from(value) as Self + } +} +impl From<Enum9> for u64 { + fn from(value: Enum9) -> Self { + u16::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: Enum7, + pub y: u8, + pub z: Enum9, + pub w: u8, +} +impl Foo { + pub fn x(&self) -> Enum7 { + self.x + } + pub fn y(&self) -> u8 { + self.y + } + pub fn z(&self) -> Enum9 { + self.z + } + pub fn w(&self) -> u8 { + self.w + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 3 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.y() > 0x1f { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "y", + value: self.y() as u64, + maximum_value: 0x1f as u64, + }); + } + if self.w() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "w", + value: self.w() as u64, + maximum_value: 0x7 as u64, + }); + } + let value = (u8::from(self.x()) as u32) | ((self.y() as u32) << 7) + | ((u16::from(self.z()) as u32) << 12) | ((self.w() as u32) << 21); + buf.put_uint(value as u64, 3); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let chunk = buf.get_uint(3) as u32; + let x = Enum7::try_from((chunk & 0x7f) as u8) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "x", + value: unknown_val as u64, + type_: "Enum7", + })?; + let y = ((chunk >> 7) & 0x1f) as u8; + let z = Enum9::try_from(((chunk >> 12) & 0x1ff) as u16) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "z", + value: unknown_val as u64, + type_: "Enum9", + })?; + let w = ((chunk >> 21) & 0x7) as u8; + Ok((Self { x, y, z, w }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_mixed_scalars_enums_little_endian.rs b/tests/generated/rust/packet_decl_mixed_scalars_enums_little_endian.rs new file mode 100644 index 0000000..77ed48e --- /dev/null +++ b/tests/generated/rust/packet_decl_mixed_scalars_enums_little_endian.rs @@ -0,0 +1,223 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[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 Enum7 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u8> for Enum7 { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum7::A), + 0x2 => Ok(Enum7::B), + _ => Err(value), + } + } +} +impl From<&Enum7> for u8 { + fn from(value: &Enum7) -> Self { + match value { + Enum7::A => 0x1, + Enum7::B => 0x2, + } + } +} +impl From<Enum7> for u8 { + fn from(value: Enum7) -> Self { + (&value).into() + } +} +impl From<Enum7> for i8 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for i16 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for i32 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for i64 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for u16 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for u32 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +impl From<Enum7> for u64 { + fn from(value: Enum7) -> Self { + u8::from(value) as Self + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u16", into = "u16"))] +pub enum Enum9 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u16> for Enum9 { + type Error = u16; + fn try_from(value: u16) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum9::A), + 0x2 => Ok(Enum9::B), + _ => Err(value), + } + } +} +impl From<&Enum9> for u16 { + fn from(value: &Enum9) -> Self { + match value { + Enum9::A => 0x1, + Enum9::B => 0x2, + } + } +} +impl From<Enum9> for u16 { + fn from(value: Enum9) -> Self { + (&value).into() + } +} +impl From<Enum9> for i16 { + fn from(value: Enum9) -> Self { + u16::from(value) as Self + } +} +impl From<Enum9> for i32 { + fn from(value: Enum9) -> Self { + u16::from(value) as Self + } +} +impl From<Enum9> for i64 { + fn from(value: Enum9) -> Self { + u16::from(value) as Self + } +} +impl From<Enum9> for u32 { + fn from(value: Enum9) -> Self { + u16::from(value) as Self + } +} +impl From<Enum9> for u64 { + fn from(value: Enum9) -> Self { + u16::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: Enum7, + pub y: u8, + pub z: Enum9, + pub w: u8, +} +impl Foo { + pub fn x(&self) -> Enum7 { + self.x + } + pub fn y(&self) -> u8 { + self.y + } + pub fn z(&self) -> Enum9 { + self.z + } + pub fn w(&self) -> u8 { + self.w + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 3 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.y() > 0x1f { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "y", + value: self.y() as u64, + maximum_value: 0x1f as u64, + }); + } + if self.w() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "w", + value: self.w() as u64, + maximum_value: 0x7 as u64, + }); + } + let value = (u8::from(self.x()) as u32) | ((self.y() as u32) << 7) + | ((u16::from(self.z()) as u32) << 12) | ((self.w() as u32) << 21); + buf.put_uint_le(value as u64, 3); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let chunk = buf.get_uint_le(3) as u32; + let x = Enum7::try_from((chunk & 0x7f) as u8) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "x", + value: unknown_val as u64, + type_: "Enum7", + })?; + let y = ((chunk >> 7) & 0x1f) as u8; + let z = Enum9::try_from(((chunk >> 12) & 0x1ff) as u16) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "z", + value: unknown_val as u64, + type_: "Enum9", + })?; + let w = ((chunk >> 21) & 0x7) as u8; + Ok((Self { x, y, z, w }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_parent_with_alias_child_big_endian.rs b/tests/generated/rust/packet_decl_parent_with_alias_child_big_endian.rs new file mode 100644 index 0000000..35df1a2 --- /dev/null +++ b/tests/generated/rust/packet_decl_parent_with_alias_child_big_endian.rs @@ -0,0 +1,461 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[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 Enum8 { + A = 0x0, + B = 0x1, + C = 0x2, +} +impl TryFrom<u8> for Enum8 { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x0 => Ok(Enum8::A), + 0x1 => Ok(Enum8::B), + 0x2 => Ok(Enum8::C), + _ => Err(value), + } + } +} +impl From<&Enum8> for u8 { + fn from(value: &Enum8) -> Self { + match value { + Enum8::A => 0x0, + Enum8::B => 0x1, + Enum8::C => 0x2, + } + } +} +impl From<Enum8> for u8 { + fn from(value: Enum8) -> Self { + (&value).into() + } +} +impl From<Enum8> for i16 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for i32 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for i64 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for u16 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for u32 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for u64 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Parent { + pub v: Enum8, + pub payload: Vec<u8>, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ParentChild { + AliasChild(AliasChild), + NormalChild(NormalChild), + None, +} +impl Parent { + pub fn specialize(&self) -> Result<ParentChild, DecodeError> { + Ok( + match (self.v,) { + (_,) => ParentChild::AliasChild(self.try_into()?), + (Enum8::A,) => ParentChild::NormalChild(self.try_into()?), + _ => ParentChild::None, + }, + ) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn v(&self) -> Enum8 { + self.v + } +} +impl Packet for Parent { + fn encoded_len(&self) -> usize { + 1 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.v())); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 1, + got: buf.remaining(), + }); + } + let v = Enum8::try_from(buf.get_u8()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "v", + value: unknown_val as u64, + type_: "Enum8", + })?; + let payload = buf.to_vec(); + buf.advance(payload.len()); + Ok((Self { payload, v }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct AliasChild { + pub v: Enum8, + pub payload: Vec<u8>, +} +impl TryFrom<&Parent> for AliasChild { + type Error = DecodeError; + fn try_from(parent: &Parent) -> Result<AliasChild, Self::Error> { + AliasChild::decode_partial(&parent) + } +} +impl TryFrom<Parent> for AliasChild { + type Error = DecodeError; + fn try_from(parent: Parent) -> Result<AliasChild, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&AliasChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &AliasChild) -> Result<Parent, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Parent { v: packet.v, payload }) + } +} +impl TryFrom<AliasChild> for Parent { + type Error = EncodeError; + fn try_from(packet: AliasChild) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum AliasChildChild { + NormalGrandChild1(NormalGrandChild1), + NormalGrandChild2(NormalGrandChild2), + None, +} +impl AliasChild { + pub fn specialize(&self) -> Result<AliasChildChild, DecodeError> { + Ok( + match (self.v,) { + (Enum8::B,) => AliasChildChild::NormalGrandChild1(self.try_into()?), + (Enum8::C,) => AliasChildChild::NormalGrandChild2(self.try_into()?), + _ => AliasChildChild::None, + }, + ) + } + fn decode_partial(parent: &Parent) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + let payload = buf.to_vec(); + buf.advance(payload.len()); + if buf.is_empty() { + Ok(Self { payload, v: parent.v }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn v(&self) -> Enum8 { + self.v + } +} +impl Packet for AliasChild { + fn encoded_len(&self) -> usize { + 1 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.v())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Parent::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct NormalChild {} +impl TryFrom<&Parent> for NormalChild { + type Error = DecodeError; + fn try_from(parent: &Parent) -> Result<NormalChild, Self::Error> { + NormalChild::decode_partial(&parent) + } +} +impl TryFrom<Parent> for NormalChild { + type Error = DecodeError; + fn try_from(parent: Parent) -> Result<NormalChild, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&NormalChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &NormalChild) -> Result<Parent, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Parent { v: Enum8::A, payload }) + } +} +impl TryFrom<NormalChild> for Parent { + type Error = EncodeError; + fn try_from(packet: NormalChild) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +impl NormalChild { + fn decode_partial(parent: &Parent) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.v() != Enum8::A { + return Err(DecodeError::InvalidFieldValue { + packet: "NormalChild", + field: "v", + expected: "Enum8::A", + actual: format!("{:?}", parent.v()), + }); + } + if buf.is_empty() { Ok(Self {}) } else { Err(DecodeError::TrailingBytes) } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + Ok(()) + } + pub fn v(&self) -> Enum8 { + Enum8::A + } +} +impl Packet for NormalChild { + fn encoded_len(&self) -> usize { + 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.v())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Parent::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct NormalGrandChild1 {} +impl TryFrom<&AliasChild> for NormalGrandChild1 { + type Error = DecodeError; + fn try_from(parent: &AliasChild) -> Result<NormalGrandChild1, Self::Error> { + NormalGrandChild1::decode_partial(&parent) + } +} +impl TryFrom<AliasChild> for NormalGrandChild1 { + type Error = DecodeError; + fn try_from(parent: AliasChild) -> Result<NormalGrandChild1, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&NormalGrandChild1> for AliasChild { + type Error = EncodeError; + fn try_from(packet: &NormalGrandChild1) -> Result<AliasChild, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(AliasChild { v: Enum8::B, payload }) + } +} +impl TryFrom<NormalGrandChild1> for AliasChild { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild1) -> Result<AliasChild, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&NormalGrandChild1> for Parent { + type Error = EncodeError; + fn try_from(packet: &NormalGrandChild1) -> Result<Parent, Self::Error> { + (&AliasChild::try_from(packet)?).try_into() + } +} +impl TryFrom<NormalGrandChild1> for Parent { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild1) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +impl NormalGrandChild1 { + fn decode_partial(parent: &AliasChild) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.v() != Enum8::B { + return Err(DecodeError::InvalidFieldValue { + packet: "NormalGrandChild1", + field: "v", + expected: "Enum8::B", + actual: format!("{:?}", parent.v()), + }); + } + if buf.is_empty() { Ok(Self {}) } else { Err(DecodeError::TrailingBytes) } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + Ok(()) + } + pub fn v(&self) -> Enum8 { + Enum8::B + } +} +impl Packet for NormalGrandChild1 { + fn encoded_len(&self) -> usize { + 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.v())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = AliasChild::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct NormalGrandChild2 { + pub payload: Vec<u8>, +} +impl TryFrom<&AliasChild> for NormalGrandChild2 { + type Error = DecodeError; + fn try_from(parent: &AliasChild) -> Result<NormalGrandChild2, Self::Error> { + NormalGrandChild2::decode_partial(&parent) + } +} +impl TryFrom<AliasChild> for NormalGrandChild2 { + type Error = DecodeError; + fn try_from(parent: AliasChild) -> Result<NormalGrandChild2, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&NormalGrandChild2> for AliasChild { + type Error = EncodeError; + fn try_from(packet: &NormalGrandChild2) -> Result<AliasChild, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(AliasChild { v: Enum8::C, payload }) + } +} +impl TryFrom<NormalGrandChild2> for AliasChild { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild2) -> Result<AliasChild, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&NormalGrandChild2> for Parent { + type Error = EncodeError; + fn try_from(packet: &NormalGrandChild2) -> Result<Parent, Self::Error> { + (&AliasChild::try_from(packet)?).try_into() + } +} +impl TryFrom<NormalGrandChild2> for Parent { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild2) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +impl NormalGrandChild2 { + fn decode_partial(parent: &AliasChild) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.v() != Enum8::C { + return Err(DecodeError::InvalidFieldValue { + packet: "NormalGrandChild2", + field: "v", + expected: "Enum8::C", + actual: format!("{:?}", parent.v()), + }); + } + let payload = buf.to_vec(); + buf.advance(payload.len()); + if buf.is_empty() { + Ok(Self { payload }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn v(&self) -> Enum8 { + Enum8::C + } +} +impl Packet for NormalGrandChild2 { + fn encoded_len(&self) -> usize { + 1 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.v())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = AliasChild::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/generated/rust/packet_decl_parent_with_alias_child_little_endian.rs b/tests/generated/rust/packet_decl_parent_with_alias_child_little_endian.rs new file mode 100644 index 0000000..35df1a2 --- /dev/null +++ b/tests/generated/rust/packet_decl_parent_with_alias_child_little_endian.rs @@ -0,0 +1,461 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[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 Enum8 { + A = 0x0, + B = 0x1, + C = 0x2, +} +impl TryFrom<u8> for Enum8 { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x0 => Ok(Enum8::A), + 0x1 => Ok(Enum8::B), + 0x2 => Ok(Enum8::C), + _ => Err(value), + } + } +} +impl From<&Enum8> for u8 { + fn from(value: &Enum8) -> Self { + match value { + Enum8::A => 0x0, + Enum8::B => 0x1, + Enum8::C => 0x2, + } + } +} +impl From<Enum8> for u8 { + fn from(value: Enum8) -> Self { + (&value).into() + } +} +impl From<Enum8> for i16 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for i32 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for i64 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for u16 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for u32 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for u64 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Parent { + pub v: Enum8, + pub payload: Vec<u8>, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ParentChild { + AliasChild(AliasChild), + NormalChild(NormalChild), + None, +} +impl Parent { + pub fn specialize(&self) -> Result<ParentChild, DecodeError> { + Ok( + match (self.v,) { + (_,) => ParentChild::AliasChild(self.try_into()?), + (Enum8::A,) => ParentChild::NormalChild(self.try_into()?), + _ => ParentChild::None, + }, + ) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn v(&self) -> Enum8 { + self.v + } +} +impl Packet for Parent { + fn encoded_len(&self) -> usize { + 1 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.v())); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 1, + got: buf.remaining(), + }); + } + let v = Enum8::try_from(buf.get_u8()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "v", + value: unknown_val as u64, + type_: "Enum8", + })?; + let payload = buf.to_vec(); + buf.advance(payload.len()); + Ok((Self { payload, v }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct AliasChild { + pub v: Enum8, + pub payload: Vec<u8>, +} +impl TryFrom<&Parent> for AliasChild { + type Error = DecodeError; + fn try_from(parent: &Parent) -> Result<AliasChild, Self::Error> { + AliasChild::decode_partial(&parent) + } +} +impl TryFrom<Parent> for AliasChild { + type Error = DecodeError; + fn try_from(parent: Parent) -> Result<AliasChild, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&AliasChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &AliasChild) -> Result<Parent, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Parent { v: packet.v, payload }) + } +} +impl TryFrom<AliasChild> for Parent { + type Error = EncodeError; + fn try_from(packet: AliasChild) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum AliasChildChild { + NormalGrandChild1(NormalGrandChild1), + NormalGrandChild2(NormalGrandChild2), + None, +} +impl AliasChild { + pub fn specialize(&self) -> Result<AliasChildChild, DecodeError> { + Ok( + match (self.v,) { + (Enum8::B,) => AliasChildChild::NormalGrandChild1(self.try_into()?), + (Enum8::C,) => AliasChildChild::NormalGrandChild2(self.try_into()?), + _ => AliasChildChild::None, + }, + ) + } + fn decode_partial(parent: &Parent) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + let payload = buf.to_vec(); + buf.advance(payload.len()); + if buf.is_empty() { + Ok(Self { payload, v: parent.v }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn v(&self) -> Enum8 { + self.v + } +} +impl Packet for AliasChild { + fn encoded_len(&self) -> usize { + 1 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.v())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Parent::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct NormalChild {} +impl TryFrom<&Parent> for NormalChild { + type Error = DecodeError; + fn try_from(parent: &Parent) -> Result<NormalChild, Self::Error> { + NormalChild::decode_partial(&parent) + } +} +impl TryFrom<Parent> for NormalChild { + type Error = DecodeError; + fn try_from(parent: Parent) -> Result<NormalChild, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&NormalChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &NormalChild) -> Result<Parent, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Parent { v: Enum8::A, payload }) + } +} +impl TryFrom<NormalChild> for Parent { + type Error = EncodeError; + fn try_from(packet: NormalChild) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +impl NormalChild { + fn decode_partial(parent: &Parent) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.v() != Enum8::A { + return Err(DecodeError::InvalidFieldValue { + packet: "NormalChild", + field: "v", + expected: "Enum8::A", + actual: format!("{:?}", parent.v()), + }); + } + if buf.is_empty() { Ok(Self {}) } else { Err(DecodeError::TrailingBytes) } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + Ok(()) + } + pub fn v(&self) -> Enum8 { + Enum8::A + } +} +impl Packet for NormalChild { + fn encoded_len(&self) -> usize { + 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.v())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Parent::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct NormalGrandChild1 {} +impl TryFrom<&AliasChild> for NormalGrandChild1 { + type Error = DecodeError; + fn try_from(parent: &AliasChild) -> Result<NormalGrandChild1, Self::Error> { + NormalGrandChild1::decode_partial(&parent) + } +} +impl TryFrom<AliasChild> for NormalGrandChild1 { + type Error = DecodeError; + fn try_from(parent: AliasChild) -> Result<NormalGrandChild1, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&NormalGrandChild1> for AliasChild { + type Error = EncodeError; + fn try_from(packet: &NormalGrandChild1) -> Result<AliasChild, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(AliasChild { v: Enum8::B, payload }) + } +} +impl TryFrom<NormalGrandChild1> for AliasChild { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild1) -> Result<AliasChild, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&NormalGrandChild1> for Parent { + type Error = EncodeError; + fn try_from(packet: &NormalGrandChild1) -> Result<Parent, Self::Error> { + (&AliasChild::try_from(packet)?).try_into() + } +} +impl TryFrom<NormalGrandChild1> for Parent { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild1) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +impl NormalGrandChild1 { + fn decode_partial(parent: &AliasChild) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.v() != Enum8::B { + return Err(DecodeError::InvalidFieldValue { + packet: "NormalGrandChild1", + field: "v", + expected: "Enum8::B", + actual: format!("{:?}", parent.v()), + }); + } + if buf.is_empty() { Ok(Self {}) } else { Err(DecodeError::TrailingBytes) } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + Ok(()) + } + pub fn v(&self) -> Enum8 { + Enum8::B + } +} +impl Packet for NormalGrandChild1 { + fn encoded_len(&self) -> usize { + 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.v())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = AliasChild::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct NormalGrandChild2 { + pub payload: Vec<u8>, +} +impl TryFrom<&AliasChild> for NormalGrandChild2 { + type Error = DecodeError; + fn try_from(parent: &AliasChild) -> Result<NormalGrandChild2, Self::Error> { + NormalGrandChild2::decode_partial(&parent) + } +} +impl TryFrom<AliasChild> for NormalGrandChild2 { + type Error = DecodeError; + fn try_from(parent: AliasChild) -> Result<NormalGrandChild2, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&NormalGrandChild2> for AliasChild { + type Error = EncodeError; + fn try_from(packet: &NormalGrandChild2) -> Result<AliasChild, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(AliasChild { v: Enum8::C, payload }) + } +} +impl TryFrom<NormalGrandChild2> for AliasChild { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild2) -> Result<AliasChild, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&NormalGrandChild2> for Parent { + type Error = EncodeError; + fn try_from(packet: &NormalGrandChild2) -> Result<Parent, Self::Error> { + (&AliasChild::try_from(packet)?).try_into() + } +} +impl TryFrom<NormalGrandChild2> for Parent { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild2) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +impl NormalGrandChild2 { + fn decode_partial(parent: &AliasChild) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.v() != Enum8::C { + return Err(DecodeError::InvalidFieldValue { + packet: "NormalGrandChild2", + field: "v", + expected: "Enum8::C", + actual: format!("{:?}", parent.v()), + }); + } + let payload = buf.to_vec(); + buf.advance(payload.len()); + if buf.is_empty() { + Ok(Self { payload }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn v(&self) -> Enum8 { + Enum8::C + } +} +impl Packet for NormalGrandChild2 { + fn encoded_len(&self) -> usize { + 1 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.v())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = AliasChild::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/generated/rust/packet_decl_parent_with_no_payload_big_endian.rs b/tests/generated/rust/packet_decl_parent_with_no_payload_big_endian.rs new file mode 100644 index 0000000..7fa66a7 --- /dev/null +++ b/tests/generated/rust/packet_decl_parent_with_no_payload_big_endian.rs @@ -0,0 +1,191 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[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 Enum8 { + A = 0x0, +} +impl TryFrom<u8> for Enum8 { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x0 => Ok(Enum8::A), + _ => Err(value), + } + } +} +impl From<&Enum8> for u8 { + fn from(value: &Enum8) -> Self { + match value { + Enum8::A => 0x0, + } + } +} +impl From<Enum8> for u8 { + fn from(value: Enum8) -> Self { + (&value).into() + } +} +impl From<Enum8> for i16 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for i32 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for i64 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for u16 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for u32 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for u64 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Parent { + pub v: Enum8, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ParentChild { + Child(Child), + None, +} +impl Parent { + pub fn specialize(&self) -> Result<ParentChild, DecodeError> { + Ok( + match (self.v,) { + (Enum8::A,) => ParentChild::Child(self.try_into()?), + _ => ParentChild::None, + }, + ) + } + pub fn v(&self) -> Enum8 { + self.v + } +} +impl Packet for Parent { + fn encoded_len(&self) -> usize { + 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.v())); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 1, + got: buf.remaining(), + }); + } + let v = Enum8::try_from(buf.get_u8()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "v", + value: unknown_val as u64, + type_: "Enum8", + })?; + Ok((Self { v }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Child {} +impl TryFrom<&Parent> for Child { + type Error = DecodeError; + fn try_from(parent: &Parent) -> Result<Child, Self::Error> { + Child::decode_partial(&parent) + } +} +impl TryFrom<Parent> for Child { + type Error = DecodeError; + fn try_from(parent: Parent) -> Result<Child, Self::Error> { + (&parent).try_into() + } +} +impl From<&Child> for Parent { + fn from(packet: &Child) -> Parent { + Parent { v: Enum8::A } + } +} +impl From<Child> for Parent { + fn from(packet: Child) -> Parent { + (&packet).into() + } +} +impl Child { + fn decode_partial(parent: &Parent) -> Result<Self, DecodeError> { + if parent.v() != Enum8::A { + return Err(DecodeError::InvalidFieldValue { + packet: "Child", + field: "v", + expected: "Enum8::A", + actual: format!("{:?}", parent.v()), + }); + } + Ok(Self {}) + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + Ok(()) + } + pub fn v(&self) -> Enum8 { + Enum8::A + } +} +impl Packet for Child { + fn encoded_len(&self) -> usize { + 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.v())); + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Parent::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/generated/rust/packet_decl_parent_with_no_payload_little_endian.rs b/tests/generated/rust/packet_decl_parent_with_no_payload_little_endian.rs new file mode 100644 index 0000000..7fa66a7 --- /dev/null +++ b/tests/generated/rust/packet_decl_parent_with_no_payload_little_endian.rs @@ -0,0 +1,191 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[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 Enum8 { + A = 0x0, +} +impl TryFrom<u8> for Enum8 { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x0 => Ok(Enum8::A), + _ => Err(value), + } + } +} +impl From<&Enum8> for u8 { + fn from(value: &Enum8) -> Self { + match value { + Enum8::A => 0x0, + } + } +} +impl From<Enum8> for u8 { + fn from(value: Enum8) -> Self { + (&value).into() + } +} +impl From<Enum8> for i16 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for i32 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for i64 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for u16 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for u32 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +impl From<Enum8> for u64 { + fn from(value: Enum8) -> Self { + u8::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Parent { + pub v: Enum8, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ParentChild { + Child(Child), + None, +} +impl Parent { + pub fn specialize(&self) -> Result<ParentChild, DecodeError> { + Ok( + match (self.v,) { + (Enum8::A,) => ParentChild::Child(self.try_into()?), + _ => ParentChild::None, + }, + ) + } + pub fn v(&self) -> Enum8 { + self.v + } +} +impl Packet for Parent { + fn encoded_len(&self) -> usize { + 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.v())); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 1, + got: buf.remaining(), + }); + } + let v = Enum8::try_from(buf.get_u8()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "v", + value: unknown_val as u64, + type_: "Enum8", + })?; + Ok((Self { v }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Child {} +impl TryFrom<&Parent> for Child { + type Error = DecodeError; + fn try_from(parent: &Parent) -> Result<Child, Self::Error> { + Child::decode_partial(&parent) + } +} +impl TryFrom<Parent> for Child { + type Error = DecodeError; + fn try_from(parent: Parent) -> Result<Child, Self::Error> { + (&parent).try_into() + } +} +impl From<&Child> for Parent { + fn from(packet: &Child) -> Parent { + Parent { v: Enum8::A } + } +} +impl From<Child> for Parent { + fn from(packet: Child) -> Parent { + (&packet).into() + } +} +impl Child { + fn decode_partial(parent: &Parent) -> Result<Self, DecodeError> { + if parent.v() != Enum8::A { + return Err(DecodeError::InvalidFieldValue { + packet: "Child", + field: "v", + expected: "Enum8::A", + actual: format!("{:?}", parent.v()), + }); + } + Ok(Self {}) + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + Ok(()) + } + pub fn v(&self) -> Enum8 { + Enum8::A + } +} +impl Packet for Child { + fn encoded_len(&self) -> usize { + 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(u8::from(self.v())); + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Parent::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/generated/rust/packet_decl_payload_field_unknown_size_big_endian.rs b/tests/generated/rust/packet_decl_payload_field_unknown_size_big_endian.rs new file mode 100644 index 0000000..583f1c6 --- /dev/null +++ b/tests/generated/rust/packet_decl_payload_field_unknown_size_big_endian.rs @@ -0,0 +1,70 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u32, + pub payload: Vec<u8>, +} +impl Foo { + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn a(&self) -> u32 { + self.a + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 3 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.a() > 0xff_ffff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a() as u64, + maximum_value: 0xff_ffff as u64, + }); + } + buf.put_uint(self.a() as u64, 3); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let a = buf.get_uint(3) as u32; + let payload = buf.to_vec(); + buf.advance(payload.len()); + Ok((Self { payload, a }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_payload_field_unknown_size_little_endian.rs b/tests/generated/rust/packet_decl_payload_field_unknown_size_little_endian.rs new file mode 100644 index 0000000..04f9b1a --- /dev/null +++ b/tests/generated/rust/packet_decl_payload_field_unknown_size_little_endian.rs @@ -0,0 +1,70 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u32, + pub payload: Vec<u8>, +} +impl Foo { + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn a(&self) -> u32 { + self.a + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 3 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.a() > 0xff_ffff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a() as u64, + maximum_value: 0xff_ffff as u64, + }); + } + buf.put_uint_le(self.a() as u64, 3); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let a = buf.get_uint_le(3) as u32; + let payload = buf.to_vec(); + buf.advance(payload.len()); + Ok((Self { payload, a }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_payload_field_unknown_size_terminal_big_endian.rs b/tests/generated/rust/packet_decl_payload_field_unknown_size_terminal_big_endian.rs new file mode 100644 index 0000000..8b56781 --- /dev/null +++ b/tests/generated/rust/packet_decl_payload_field_unknown_size_terminal_big_endian.rs @@ -0,0 +1,77 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u32, + pub payload: Vec<u8>, +} +impl Foo { + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn a(&self) -> u32 { + self.a + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 3 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + if self.a() > 0xff_ffff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a() as u64, + maximum_value: 0xff_ffff as u64, + }); + } + buf.put_uint(self.a() as u64, 3); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let payload = buf[..buf.len() - 3].to_vec(); + buf.advance(payload.len()); + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let a = buf.get_uint(3) as u32; + Ok((Self { payload, a }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_payload_field_unknown_size_terminal_little_endian.rs b/tests/generated/rust/packet_decl_payload_field_unknown_size_terminal_little_endian.rs new file mode 100644 index 0000000..6f4d71c --- /dev/null +++ b/tests/generated/rust/packet_decl_payload_field_unknown_size_terminal_little_endian.rs @@ -0,0 +1,77 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u32, + pub payload: Vec<u8>, +} +impl Foo { + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn a(&self) -> u32 { + self.a + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 3 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + if self.a() > 0xff_ffff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a() as u64, + maximum_value: 0xff_ffff as u64, + }); + } + buf.put_uint_le(self.a() as u64, 3); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let payload = buf[..buf.len() - 3].to_vec(); + buf.advance(payload.len()); + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let a = buf.get_uint_le(3) as u32; + Ok((Self { payload, a }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_payload_field_variable_size_big_endian.rs b/tests/generated/rust/packet_decl_payload_field_variable_size_big_endian.rs new file mode 100644 index 0000000..4c5d8b3 --- /dev/null +++ b/tests/generated/rust/packet_decl_payload_field_variable_size_big_endian.rs @@ -0,0 +1,99 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u8, + pub b: u16, + pub payload: Vec<u8>, +} +impl Foo { + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> u16 { + self.b + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 4 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + if self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(self.payload.len() as u8); + buf.put_slice(&self.payload); + buf.put_u16(self.b()); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let a = buf.get_u8(); + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let b = buf.get_u16(); + Ok((Self { payload, a, b }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_payload_field_variable_size_little_endian.rs b/tests/generated/rust/packet_decl_payload_field_variable_size_little_endian.rs new file mode 100644 index 0000000..f82f777 --- /dev/null +++ b/tests/generated/rust/packet_decl_payload_field_variable_size_little_endian.rs @@ -0,0 +1,99 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u8, + pub b: u16, + pub payload: Vec<u8>, +} +impl Foo { + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> u16 { + self.b + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 4 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + if self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(self.payload.len() as u8); + buf.put_slice(&self.payload); + buf.put_u16_le(self.b()); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let a = buf.get_u8(); + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let b = buf.get_u16_le(); + Ok((Self { payload, a, b }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_reserved_field_big_endian.rs b/tests/generated/rust/packet_decl_reserved_field_big_endian.rs new file mode 100644 index 0000000..0eaeb23 --- /dev/null +++ b/tests/generated/rust/packet_decl_reserved_field_big_endian.rs @@ -0,0 +1,49 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo {} +impl Foo {} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 5 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_bytes(0, 5); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 5, + got: buf.remaining(), + }); + } + buf.advance(5); + Ok((Self {}, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_reserved_field_little_endian.rs b/tests/generated/rust/packet_decl_reserved_field_little_endian.rs new file mode 100644 index 0000000..0eaeb23 --- /dev/null +++ b/tests/generated/rust/packet_decl_reserved_field_little_endian.rs @@ -0,0 +1,49 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo {} +impl Foo {} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 5 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_bytes(0, 5); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 5 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 5, + got: buf.remaining(), + }); + } + buf.advance(5); + Ok((Self {}, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_simple_scalars_big_endian.rs b/tests/generated/rust/packet_decl_simple_scalars_big_endian.rs new file mode 100644 index 0000000..e1c39d3 --- /dev/null +++ b/tests/generated/rust/packet_decl_simple_scalars_big_endian.rs @@ -0,0 +1,89 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: u8, + pub y: u16, + pub z: u32, +} +impl Foo { + pub fn x(&self) -> u8 { + self.x + } + pub fn y(&self) -> u16 { + self.y + } + pub fn z(&self) -> u32 { + self.z + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 6 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.x()); + buf.put_u16(self.y()); + if self.z() > 0xff_ffff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "z", + value: self.z() as u64, + maximum_value: 0xff_ffff as u64, + }); + } + buf.put_uint(self.z() as u64, 3); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let x = buf.get_u8(); + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let y = buf.get_u16(); + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let z = buf.get_uint(3) as u32; + Ok((Self { x, y, z }, buf)) + } +} diff --git a/tests/generated/rust/packet_decl_simple_scalars_little_endian.rs b/tests/generated/rust/packet_decl_simple_scalars_little_endian.rs new file mode 100644 index 0000000..e6560dc --- /dev/null +++ b/tests/generated/rust/packet_decl_simple_scalars_little_endian.rs @@ -0,0 +1,89 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub x: u8, + pub y: u16, + pub z: u32, +} +impl Foo { + pub fn x(&self) -> u8 { + self.x + } + pub fn y(&self) -> u16 { + self.y + } + pub fn z(&self) -> u32 { + self.z + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 6 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.x()); + buf.put_u16_le(self.y()); + if self.z() > 0xff_ffff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "z", + value: self.z() as u64, + maximum_value: 0xff_ffff as u64, + }); + } + buf.put_uint_le(self.z() as u64, 3); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let x = buf.get_u8(); + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let y = buf.get_u16_le(); + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let z = buf.get_uint_le(3) as u32; + Ok((Self { x, y, z }, buf)) + } +} diff --git a/tests/generated/rust/payload_with_size_modifier_big_endian.rs b/tests/generated/rust/payload_with_size_modifier_big_endian.rs new file mode 100644 index 0000000..a0411dc --- /dev/null +++ b/tests/generated/rust/payload_with_size_modifier_big_endian.rs @@ -0,0 +1,81 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Test { + pub payload: Vec<u8>, +} +impl Test { + pub fn payload(&self) -> &[u8] { + &self.payload + } +} +impl Packet for Test { + fn encoded_len(&self) -> usize { + 1 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if (self.payload.len() + 1) > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Test", + field: "_payload_", + size: (self.payload.len() + 1), + maximum_size: 0xff, + }); + } + buf.put_u8((self.payload.len() + 1) as u8); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Test", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if payload_size < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Test", + wanted: 1, + got: payload_size, + }); + } + let payload_size = payload_size - 1; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Test", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + Ok((Self { payload }, buf)) + } +} diff --git a/tests/generated/rust/payload_with_size_modifier_little_endian.rs b/tests/generated/rust/payload_with_size_modifier_little_endian.rs new file mode 100644 index 0000000..a0411dc --- /dev/null +++ b/tests/generated/rust/payload_with_size_modifier_little_endian.rs @@ -0,0 +1,81 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Test { + pub payload: Vec<u8>, +} +impl Test { + pub fn payload(&self) -> &[u8] { + &self.payload + } +} +impl Packet for Test { + fn encoded_len(&self) -> usize { + 1 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if (self.payload.len() + 1) > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Test", + field: "_payload_", + size: (self.payload.len() + 1), + maximum_size: 0xff, + }); + } + buf.put_u8((self.payload.len() + 1) as u8); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Test", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if payload_size < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Test", + wanted: 1, + got: payload_size, + }); + } + let payload_size = payload_size - 1; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Test", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + Ok((Self { payload }, buf)) + } +} diff --git a/tests/generated/rust/reserved_identifier_big_endian.rs b/tests/generated/rust/reserved_identifier_big_endian.rs new file mode 100644 index 0000000..17ee5a3 --- /dev/null +++ b/tests/generated/rust/reserved_identifier_big_endian.rs @@ -0,0 +1,55 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Test { + pub r#type: u8, +} +impl Test { + pub fn r#type(&self) -> u8 { + self.r#type + } +} +impl Packet for Test { + fn encoded_len(&self) -> usize { + 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.r#type()); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Test", + wanted: 1, + got: buf.remaining(), + }); + } + let r#type = buf.get_u8(); + Ok((Self { r#type }, buf)) + } +} diff --git a/tests/generated/rust/reserved_identifier_little_endian.rs b/tests/generated/rust/reserved_identifier_little_endian.rs new file mode 100644 index 0000000..17ee5a3 --- /dev/null +++ b/tests/generated/rust/reserved_identifier_little_endian.rs @@ -0,0 +1,55 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Test { + pub r#type: u8, +} +impl Test { + pub fn r#type(&self) -> u8 { + self.r#type + } +} +impl Packet for Test { + fn encoded_len(&self) -> usize { + 1 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.r#type()); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Test", + wanted: 1, + got: buf.remaining(), + }); + } + let r#type = buf.get_u8(); + Ok((Self { r#type }, buf)) + } +} diff --git a/tests/generated/rust/struct_decl_child_structs_big_endian.rs b/tests/generated/rust/struct_decl_child_structs_big_endian.rs new file mode 100644 index 0000000..9653e2d --- /dev/null +++ b/tests/generated/rust/struct_decl_child_structs_big_endian.rs @@ -0,0 +1,373 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u16", into = "u16"))] +pub enum Enum16 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u16> for Enum16 { + type Error = u16; + fn try_from(value: u16) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum16::A), + 0x2 => Ok(Enum16::B), + _ => Err(value), + } + } +} +impl From<&Enum16> for u16 { + fn from(value: &Enum16) -> Self { + match value { + Enum16::A => 0x1, + Enum16::B => 0x2, + } + } +} +impl From<Enum16> for u16 { + fn from(value: Enum16) -> Self { + (&value).into() + } +} +impl From<Enum16> for i32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for i64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u8, + pub b: Enum16, + pub payload: Vec<u8>, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum FooChild { + Bar(Bar), + Baz(Baz), + None, +} +impl Foo { + pub fn specialize(&self) -> Result<FooChild, DecodeError> { + Ok( + match (self.a, self.b) { + (100, _) => FooChild::Bar(self.try_into()?), + (_, Enum16::B) => FooChild::Baz(self.try_into()?), + _ => FooChild::None, + }, + ) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> Enum16 { + self.b + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 4 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16(u16::from(self.b())); + if self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(self.payload.len() as u8); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let a = buf.get_u8(); + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let b = Enum16::try_from(buf.get_u16()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "b", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + let payload = Vec::from(payload); + Ok((Self { payload, a, b }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: u8, + pub b: Enum16, +} +impl TryFrom<&Foo> for Bar { + type Error = DecodeError; + fn try_from(parent: &Foo) -> Result<Bar, Self::Error> { + Bar::decode_partial(&parent) + } +} +impl TryFrom<Foo> for Bar { + type Error = DecodeError; + fn try_from(parent: Foo) -> Result<Bar, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&Bar> for Foo { + type Error = EncodeError; + fn try_from(packet: &Bar) -> Result<Foo, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Foo { + a: 100, + b: packet.b, + payload, + }) + } +} +impl TryFrom<Bar> for Foo { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Foo, Self::Error> { + (&packet).try_into() + } +} +impl Bar { + fn decode_partial(parent: &Foo) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.a() != 100 { + return Err(DecodeError::InvalidFieldValue { + packet: "Bar", + field: "a", + expected: "100", + actual: format!("{:?}", parent.a()), + }); + } + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let x = buf.get_u8(); + if buf.is_empty() { + Ok(Self { x, b: parent.b }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.x()); + Ok(()) + } + pub fn x(&self) -> u8 { + self.x + } + pub fn b(&self) -> Enum16 { + self.b + } + pub fn a(&self) -> u8 { + 100 + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 5 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16(u16::from(self.b())); + if 1 > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: 1, + maximum_size: 0xff, + }); + } + buf.put_u8(1 as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Foo::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Baz { + pub y: u16, + pub a: u8, +} +impl TryFrom<&Foo> for Baz { + type Error = DecodeError; + fn try_from(parent: &Foo) -> Result<Baz, Self::Error> { + Baz::decode_partial(&parent) + } +} +impl TryFrom<Foo> for Baz { + type Error = DecodeError; + fn try_from(parent: Foo) -> Result<Baz, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&Baz> for Foo { + type Error = EncodeError; + fn try_from(packet: &Baz) -> Result<Foo, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Foo { + a: packet.a, + b: Enum16::B, + payload, + }) + } +} +impl TryFrom<Baz> for Foo { + type Error = EncodeError; + fn try_from(packet: Baz) -> Result<Foo, Self::Error> { + (&packet).try_into() + } +} +impl Baz { + fn decode_partial(parent: &Foo) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.b() != Enum16::B { + return Err(DecodeError::InvalidFieldValue { + packet: "Baz", + field: "b", + expected: "Enum16::B", + actual: format!("{:?}", parent.b()), + }); + } + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Baz", + wanted: 2, + got: buf.remaining(), + }); + } + let y = buf.get_u16(); + if buf.is_empty() { + Ok(Self { y, a: parent.a }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(self.y()); + Ok(()) + } + pub fn y(&self) -> u16 { + self.y + } + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> Enum16 { + Enum16::B + } +} +impl Packet for Baz { + fn encoded_len(&self) -> usize { + 6 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16(u16::from(self.b())); + if 2 > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: 2, + maximum_size: 0xff, + }); + } + buf.put_u8(2 as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Foo::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/generated/rust/struct_decl_child_structs_little_endian.rs b/tests/generated/rust/struct_decl_child_structs_little_endian.rs new file mode 100644 index 0000000..20fc72c --- /dev/null +++ b/tests/generated/rust/struct_decl_child_structs_little_endian.rs @@ -0,0 +1,373 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u16", into = "u16"))] +pub enum Enum16 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u16> for Enum16 { + type Error = u16; + fn try_from(value: u16) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum16::A), + 0x2 => Ok(Enum16::B), + _ => Err(value), + } + } +} +impl From<&Enum16> for u16 { + fn from(value: &Enum16) -> Self { + match value { + Enum16::A => 0x1, + Enum16::B => 0x2, + } + } +} +impl From<Enum16> for u16 { + fn from(value: Enum16) -> Self { + (&value).into() + } +} +impl From<Enum16> for i32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for i64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u8, + pub b: Enum16, + pub payload: Vec<u8>, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum FooChild { + Bar(Bar), + Baz(Baz), + None, +} +impl Foo { + pub fn specialize(&self) -> Result<FooChild, DecodeError> { + Ok( + match (self.a, self.b) { + (100, _) => FooChild::Bar(self.try_into()?), + (_, Enum16::B) => FooChild::Baz(self.try_into()?), + _ => FooChild::None, + }, + ) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> Enum16 { + self.b + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 4 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16_le(u16::from(self.b())); + if self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(self.payload.len() as u8); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let a = buf.get_u8(); + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let b = Enum16::try_from(buf.get_u16_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "b", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + let payload = Vec::from(payload); + Ok((Self { payload, a, b }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: u8, + pub b: Enum16, +} +impl TryFrom<&Foo> for Bar { + type Error = DecodeError; + fn try_from(parent: &Foo) -> Result<Bar, Self::Error> { + Bar::decode_partial(&parent) + } +} +impl TryFrom<Foo> for Bar { + type Error = DecodeError; + fn try_from(parent: Foo) -> Result<Bar, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&Bar> for Foo { + type Error = EncodeError; + fn try_from(packet: &Bar) -> Result<Foo, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Foo { + a: 100, + b: packet.b, + payload, + }) + } +} +impl TryFrom<Bar> for Foo { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Foo, Self::Error> { + (&packet).try_into() + } +} +impl Bar { + fn decode_partial(parent: &Foo) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.a() != 100 { + return Err(DecodeError::InvalidFieldValue { + packet: "Bar", + field: "a", + expected: "100", + actual: format!("{:?}", parent.a()), + }); + } + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let x = buf.get_u8(); + if buf.is_empty() { + Ok(Self { x, b: parent.b }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.x()); + Ok(()) + } + pub fn x(&self) -> u8 { + self.x + } + pub fn b(&self) -> Enum16 { + self.b + } + pub fn a(&self) -> u8 { + 100 + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 5 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16_le(u16::from(self.b())); + if 1 > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: 1, + maximum_size: 0xff, + }); + } + buf.put_u8(1 as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Foo::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Baz { + pub y: u16, + pub a: u8, +} +impl TryFrom<&Foo> for Baz { + type Error = DecodeError; + fn try_from(parent: &Foo) -> Result<Baz, Self::Error> { + Baz::decode_partial(&parent) + } +} +impl TryFrom<Foo> for Baz { + type Error = DecodeError; + fn try_from(parent: Foo) -> Result<Baz, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&Baz> for Foo { + type Error = EncodeError; + fn try_from(packet: &Baz) -> Result<Foo, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Foo { + a: packet.a, + b: Enum16::B, + payload, + }) + } +} +impl TryFrom<Baz> for Foo { + type Error = EncodeError; + fn try_from(packet: Baz) -> Result<Foo, Self::Error> { + (&packet).try_into() + } +} +impl Baz { + fn decode_partial(parent: &Foo) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.b() != Enum16::B { + return Err(DecodeError::InvalidFieldValue { + packet: "Baz", + field: "b", + expected: "Enum16::B", + actual: format!("{:?}", parent.b()), + }); + } + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Baz", + wanted: 2, + got: buf.remaining(), + }); + } + let y = buf.get_u16_le(); + if buf.is_empty() { + Ok(Self { y, a: parent.a }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(self.y()); + Ok(()) + } + pub fn y(&self) -> u16 { + self.y + } + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> Enum16 { + Enum16::B + } +} +impl Packet for Baz { + fn encoded_len(&self) -> usize { + 6 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16_le(u16::from(self.b())); + if 2 > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: 2, + maximum_size: 0xff, + }); + } + buf.put_u8(2 as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Foo::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/generated/rust/struct_decl_complex_scalars_big_endian.rs b/tests/generated/rust/struct_decl_complex_scalars_big_endian.rs new file mode 100644 index 0000000..e2f6e8c --- /dev/null +++ b/tests/generated/rust/struct_decl_complex_scalars_big_endian.rs @@ -0,0 +1,141 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u8, + pub b: u8, + pub c: u8, + pub d: u32, + pub e: u16, + pub f: u8, +} +impl Foo { + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> u8 { + self.b + } + pub fn c(&self) -> u8 { + self.c + } + pub fn d(&self) -> u32 { + self.d + } + pub fn e(&self) -> u16 { + self.e + } + pub fn f(&self) -> u8 { + self.f + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 7 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.a() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a() as u64, + maximum_value: 0x7 as u64, + }); + } + if self.c() > 0x1f { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "c", + value: self.c() as u64, + maximum_value: 0x1f as u64, + }); + } + let value = (self.a() as u16) | ((self.b() as u16) << 3) + | ((self.c() as u16) << 11); + buf.put_u16(value); + if self.d() > 0xff_ffff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "d", + value: self.d() as u64, + maximum_value: 0xff_ffff as u64, + }); + } + buf.put_uint(self.d() as u64, 3); + if self.e() > 0xfff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "e", + value: self.e() as u64, + maximum_value: 0xfff as u64, + }); + } + if self.f() > 0xf { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "f", + value: self.f() as u64, + maximum_value: 0xf as u64, + }); + } + let value = self.e() | ((self.f() as u16) << 12); + buf.put_u16(value); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let chunk = buf.get_u16(); + let a = (chunk & 0x7) as u8; + let b = (chunk >> 3) as u8; + let c = ((chunk >> 11) & 0x1f) as u8; + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let d = buf.get_uint(3) as u32; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let chunk = buf.get_u16(); + let e = (chunk & 0xfff); + let f = ((chunk >> 12) & 0xf) as u8; + Ok((Self { a, b, c, d, e, f }, buf)) + } +} diff --git a/tests/generated/rust/struct_decl_complex_scalars_little_endian.rs b/tests/generated/rust/struct_decl_complex_scalars_little_endian.rs new file mode 100644 index 0000000..b18d238 --- /dev/null +++ b/tests/generated/rust/struct_decl_complex_scalars_little_endian.rs @@ -0,0 +1,141 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u8, + pub b: u8, + pub c: u8, + pub d: u32, + pub e: u16, + pub f: u8, +} +impl Foo { + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> u8 { + self.b + } + pub fn c(&self) -> u8 { + self.c + } + pub fn d(&self) -> u32 { + self.d + } + pub fn e(&self) -> u16 { + self.e + } + pub fn f(&self) -> u8 { + self.f + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 7 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + if self.a() > 0x7 { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a() as u64, + maximum_value: 0x7 as u64, + }); + } + if self.c() > 0x1f { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "c", + value: self.c() as u64, + maximum_value: 0x1f as u64, + }); + } + let value = (self.a() as u16) | ((self.b() as u16) << 3) + | ((self.c() as u16) << 11); + buf.put_u16_le(value); + if self.d() > 0xff_ffff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "d", + value: self.d() as u64, + maximum_value: 0xff_ffff as u64, + }); + } + buf.put_uint_le(self.d() as u64, 3); + if self.e() > 0xfff { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "e", + value: self.e() as u64, + maximum_value: 0xfff as u64, + }); + } + if self.f() > 0xf { + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "f", + value: self.f() as u64, + maximum_value: 0xf as u64, + }); + } + let value = self.e() | ((self.f() as u16) << 12); + buf.put_u16_le(value); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let chunk = buf.get_u16_le(); + let a = (chunk & 0x7) as u8; + let b = (chunk >> 3) as u8; + let c = ((chunk >> 11) & 0x1f) as u8; + if buf.remaining() < 3 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 3, + got: buf.remaining(), + }); + } + let d = buf.get_uint_le(3) as u32; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let chunk = buf.get_u16_le(); + let e = (chunk & 0xfff); + let f = ((chunk >> 12) & 0xf) as u8; + Ok((Self { a, b, c, d, e, f }, buf)) + } +} diff --git a/tests/generated/rust/struct_decl_grand_children_big_endian.rs b/tests/generated/rust/struct_decl_grand_children_big_endian.rs new file mode 100644 index 0000000..e3c124c --- /dev/null +++ b/tests/generated/rust/struct_decl_grand_children_big_endian.rs @@ -0,0 +1,598 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u16", into = "u16"))] +pub enum Enum16 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u16> for Enum16 { + type Error = u16; + fn try_from(value: u16) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum16::A), + 0x2 => Ok(Enum16::B), + _ => Err(value), + } + } +} +impl From<&Enum16> for u16 { + fn from(value: &Enum16) -> Self { + match value { + Enum16::A => 0x1, + Enum16::B => 0x2, + } + } +} +impl From<Enum16> for u16 { + fn from(value: Enum16) -> Self { + (&value).into() + } +} +impl From<Enum16> for i32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for i64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Parent { + pub foo: Enum16, + pub bar: Enum16, + pub baz: Enum16, + pub payload: Vec<u8>, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ParentChild { + Child(Child), + None, +} +impl Parent { + pub fn specialize(&self) -> Result<ParentChild, DecodeError> { + Ok( + match (self.foo,) { + (Enum16::A,) => ParentChild::Child(self.try_into()?), + _ => ParentChild::None, + }, + ) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn foo(&self) -> Enum16 { + self.foo + } + pub fn bar(&self) -> Enum16 { + self.bar + } + pub fn baz(&self) -> Enum16 { + self.baz + } +} +impl Packet for Parent { + fn encoded_len(&self) -> usize { + 7 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(u16::from(self.foo())); + buf.put_u16(u16::from(self.bar())); + buf.put_u16(u16::from(self.baz())); + if self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(self.payload.len() as u8); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let foo = Enum16::try_from(buf.get_u16()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "foo", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let bar = Enum16::try_from(buf.get_u16()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "bar", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let baz = Enum16::try_from(buf.get_u16()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "baz", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + let payload = Vec::from(payload); + Ok((Self { payload, foo, bar, baz }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Child { + pub quux: Enum16, + pub bar: Enum16, + pub baz: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Parent> for Child { + type Error = DecodeError; + fn try_from(parent: &Parent) -> Result<Child, Self::Error> { + Child::decode_partial(&parent) + } +} +impl TryFrom<Parent> for Child { + type Error = DecodeError; + fn try_from(parent: Parent) -> Result<Child, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&Child> for Parent { + type Error = EncodeError; + fn try_from(packet: &Child) -> Result<Parent, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Parent { + foo: Enum16::A, + bar: packet.bar, + baz: packet.baz, + payload, + }) + } +} +impl TryFrom<Child> for Parent { + type Error = EncodeError; + fn try_from(packet: Child) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ChildChild { + GrandChild(GrandChild), + None, +} +impl Child { + pub fn specialize(&self) -> Result<ChildChild, DecodeError> { + Ok( + match (self.bar, self.quux) { + (Enum16::A, Enum16::A) => ChildChild::GrandChild(self.try_into()?), + _ => ChildChild::None, + }, + ) + } + fn decode_partial(parent: &Parent) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.foo() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "Child", + field: "foo", + expected: "Enum16::A", + actual: format!("{:?}", parent.foo()), + }); + } + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Child", + wanted: 2, + got: buf.remaining(), + }); + } + let quux = Enum16::try_from(buf.get_u16()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Child", + field: "quux", + value: unknown_val as u64, + type_: "Enum16", + })?; + let payload = buf.to_vec(); + buf.advance(payload.len()); + let payload = Vec::from(payload); + if buf.is_empty() { + Ok(Self { + payload, + quux, + bar: parent.bar, + baz: parent.baz, + }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(u16::from(self.quux())); + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn quux(&self) -> Enum16 { + self.quux + } + pub fn bar(&self) -> Enum16 { + self.bar + } + pub fn baz(&self) -> Enum16 { + self.baz + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for Child { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(u16::from(self.foo())); + buf.put_u16(u16::from(self.bar())); + buf.put_u16(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Parent::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GrandChild { + pub baz: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Child> for GrandChild { + type Error = DecodeError; + fn try_from(parent: &Child) -> Result<GrandChild, Self::Error> { + GrandChild::decode_partial(&parent) + } +} +impl TryFrom<Child> for GrandChild { + type Error = DecodeError; + fn try_from(parent: Child) -> Result<GrandChild, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&GrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Child, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Child { + quux: Enum16::A, + bar: Enum16::A, + baz: packet.baz, + payload, + }) + } +} +impl TryFrom<GrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: GrandChild) -> Result<Child, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&GrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Parent, Self::Error> { + (&Child::try_from(packet)?).try_into() + } +} +impl TryFrom<GrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: GrandChild) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum GrandChildChild { + GrandGrandChild(GrandGrandChild), + None, +} +impl GrandChild { + pub fn specialize(&self) -> Result<GrandChildChild, DecodeError> { + Ok( + match (self.baz,) { + (Enum16::A,) => GrandChildChild::GrandGrandChild(self.try_into()?), + _ => GrandChildChild::None, + }, + ) + } + fn decode_partial(parent: &Child) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.bar() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "GrandChild", + field: "bar", + expected: "Enum16::A", + actual: format!("{:?}", parent.bar()), + }); + } + if parent.quux() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "GrandChild", + field: "quux", + expected: "Enum16::A", + actual: format!("{:?}", parent.quux()), + }); + } + let payload = buf.to_vec(); + buf.advance(payload.len()); + let payload = Vec::from(payload); + if buf.is_empty() { + Ok(Self { payload, baz: parent.baz }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn baz(&self) -> Enum16 { + self.baz + } + pub fn quux(&self) -> Enum16 { + Enum16::A + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } + pub fn bar(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for GrandChild { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(u16::from(self.foo())); + buf.put_u16(u16::from(self.bar())); + buf.put_u16(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + buf.put_u16(u16::from(self.quux())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Child::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GrandGrandChild { + pub payload: Vec<u8>, +} +impl TryFrom<&GrandChild> for GrandGrandChild { + type Error = DecodeError; + fn try_from(parent: &GrandChild) -> Result<GrandGrandChild, Self::Error> { + GrandGrandChild::decode_partial(&parent) + } +} +impl TryFrom<GrandChild> for GrandGrandChild { + type Error = DecodeError; + fn try_from(parent: GrandChild) -> Result<GrandGrandChild, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&GrandGrandChild> for GrandChild { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<GrandChild, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(GrandChild { + baz: Enum16::A, + payload, + }) + } +} +impl TryFrom<GrandGrandChild> for GrandChild { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<GrandChild, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&GrandGrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Child, Self::Error> { + (&GrandChild::try_from(packet)?).try_into() + } +} +impl TryFrom<GrandGrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<Child, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&GrandGrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Parent, Self::Error> { + (&GrandChild::try_from(packet)?).try_into() + } +} +impl TryFrom<GrandGrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +impl GrandGrandChild { + fn decode_partial(parent: &GrandChild) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.baz() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "GrandGrandChild", + field: "baz", + expected: "Enum16::A", + actual: format!("{:?}", parent.baz()), + }); + } + let payload = buf.to_vec(); + buf.advance(payload.len()); + let payload = Vec::from(payload); + if buf.is_empty() { + Ok(Self { payload }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn quux(&self) -> Enum16 { + Enum16::A + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } + pub fn bar(&self) -> Enum16 { + Enum16::A + } + pub fn baz(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for GrandGrandChild { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(u16::from(self.foo())); + buf.put_u16(u16::from(self.bar())); + buf.put_u16(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + buf.put_u16(u16::from(self.quux())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = GrandChild::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/generated/rust/struct_decl_grand_children_little_endian.rs b/tests/generated/rust/struct_decl_grand_children_little_endian.rs new file mode 100644 index 0000000..5e638d1 --- /dev/null +++ b/tests/generated/rust/struct_decl_grand_children_little_endian.rs @@ -0,0 +1,598 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u16", into = "u16"))] +pub enum Enum16 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u16> for Enum16 { + type Error = u16; + fn try_from(value: u16) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum16::A), + 0x2 => Ok(Enum16::B), + _ => Err(value), + } + } +} +impl From<&Enum16> for u16 { + fn from(value: &Enum16) -> Self { + match value { + Enum16::A => 0x1, + Enum16::B => 0x2, + } + } +} +impl From<Enum16> for u16 { + fn from(value: Enum16) -> Self { + (&value).into() + } +} +impl From<Enum16> for i32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for i64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Parent { + pub foo: Enum16, + pub bar: Enum16, + pub baz: Enum16, + pub payload: Vec<u8>, +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ParentChild { + Child(Child), + None, +} +impl Parent { + pub fn specialize(&self) -> Result<ParentChild, DecodeError> { + Ok( + match (self.foo,) { + (Enum16::A,) => ParentChild::Child(self.try_into()?), + _ => ParentChild::None, + }, + ) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn foo(&self) -> Enum16 { + self.foo + } + pub fn bar(&self) -> Enum16 { + self.bar + } + pub fn baz(&self) -> Enum16 { + self.baz + } +} +impl Packet for Parent { + fn encoded_len(&self) -> usize { + 7 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(u16::from(self.foo())); + buf.put_u16_le(u16::from(self.bar())); + buf.put_u16_le(u16::from(self.baz())); + if self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(self.payload.len() as u8); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let foo = Enum16::try_from(buf.get_u16_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "foo", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let bar = Enum16::try_from(buf.get_u16_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "bar", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let baz = Enum16::try_from(buf.get_u16_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "baz", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + let payload = Vec::from(payload); + Ok((Self { payload, foo, bar, baz }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Child { + pub quux: Enum16, + pub bar: Enum16, + pub baz: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Parent> for Child { + type Error = DecodeError; + fn try_from(parent: &Parent) -> Result<Child, Self::Error> { + Child::decode_partial(&parent) + } +} +impl TryFrom<Parent> for Child { + type Error = DecodeError; + fn try_from(parent: Parent) -> Result<Child, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&Child> for Parent { + type Error = EncodeError; + fn try_from(packet: &Child) -> Result<Parent, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Parent { + foo: Enum16::A, + bar: packet.bar, + baz: packet.baz, + payload, + }) + } +} +impl TryFrom<Child> for Parent { + type Error = EncodeError; + fn try_from(packet: Child) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ChildChild { + GrandChild(GrandChild), + None, +} +impl Child { + pub fn specialize(&self) -> Result<ChildChild, DecodeError> { + Ok( + match (self.bar, self.quux) { + (Enum16::A, Enum16::A) => ChildChild::GrandChild(self.try_into()?), + _ => ChildChild::None, + }, + ) + } + fn decode_partial(parent: &Parent) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.foo() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "Child", + field: "foo", + expected: "Enum16::A", + actual: format!("{:?}", parent.foo()), + }); + } + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Child", + wanted: 2, + got: buf.remaining(), + }); + } + let quux = Enum16::try_from(buf.get_u16_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Child", + field: "quux", + value: unknown_val as u64, + type_: "Enum16", + })?; + let payload = buf.to_vec(); + buf.advance(payload.len()); + let payload = Vec::from(payload); + if buf.is_empty() { + Ok(Self { + payload, + quux, + bar: parent.bar, + baz: parent.baz, + }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(u16::from(self.quux())); + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn quux(&self) -> Enum16 { + self.quux + } + pub fn bar(&self) -> Enum16 { + self.bar + } + pub fn baz(&self) -> Enum16 { + self.baz + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for Child { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(u16::from(self.foo())); + buf.put_u16_le(u16::from(self.bar())); + buf.put_u16_le(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Parent::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GrandChild { + pub baz: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Child> for GrandChild { + type Error = DecodeError; + fn try_from(parent: &Child) -> Result<GrandChild, Self::Error> { + GrandChild::decode_partial(&parent) + } +} +impl TryFrom<Child> for GrandChild { + type Error = DecodeError; + fn try_from(parent: Child) -> Result<GrandChild, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&GrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Child, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Child { + quux: Enum16::A, + bar: Enum16::A, + baz: packet.baz, + payload, + }) + } +} +impl TryFrom<GrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: GrandChild) -> Result<Child, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&GrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Parent, Self::Error> { + (&Child::try_from(packet)?).try_into() + } +} +impl TryFrom<GrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: GrandChild) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum GrandChildChild { + GrandGrandChild(GrandGrandChild), + None, +} +impl GrandChild { + pub fn specialize(&self) -> Result<GrandChildChild, DecodeError> { + Ok( + match (self.baz,) { + (Enum16::A,) => GrandChildChild::GrandGrandChild(self.try_into()?), + _ => GrandChildChild::None, + }, + ) + } + fn decode_partial(parent: &Child) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.bar() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "GrandChild", + field: "bar", + expected: "Enum16::A", + actual: format!("{:?}", parent.bar()), + }); + } + if parent.quux() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "GrandChild", + field: "quux", + expected: "Enum16::A", + actual: format!("{:?}", parent.quux()), + }); + } + let payload = buf.to_vec(); + buf.advance(payload.len()); + let payload = Vec::from(payload); + if buf.is_empty() { + Ok(Self { payload, baz: parent.baz }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn baz(&self) -> Enum16 { + self.baz + } + pub fn quux(&self) -> Enum16 { + Enum16::A + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } + pub fn bar(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for GrandChild { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(u16::from(self.foo())); + buf.put_u16_le(u16::from(self.bar())); + buf.put_u16_le(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + buf.put_u16_le(u16::from(self.quux())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Child::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GrandGrandChild { + pub payload: Vec<u8>, +} +impl TryFrom<&GrandChild> for GrandGrandChild { + type Error = DecodeError; + fn try_from(parent: &GrandChild) -> Result<GrandGrandChild, Self::Error> { + GrandGrandChild::decode_partial(&parent) + } +} +impl TryFrom<GrandChild> for GrandGrandChild { + type Error = DecodeError; + fn try_from(parent: GrandChild) -> Result<GrandGrandChild, Self::Error> { + (&parent).try_into() + } +} +impl TryFrom<&GrandGrandChild> for GrandChild { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<GrandChild, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(GrandChild { + baz: Enum16::A, + payload, + }) + } +} +impl TryFrom<GrandGrandChild> for GrandChild { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<GrandChild, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&GrandGrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Child, Self::Error> { + (&GrandChild::try_from(packet)?).try_into() + } +} +impl TryFrom<GrandGrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<Child, Self::Error> { + (&packet).try_into() + } +} +impl TryFrom<&GrandGrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Parent, Self::Error> { + (&GrandChild::try_from(packet)?).try_into() + } +} +impl TryFrom<GrandGrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<Parent, Self::Error> { + (&packet).try_into() + } +} +impl GrandGrandChild { + fn decode_partial(parent: &GrandChild) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if parent.baz() != Enum16::A { + return Err(DecodeError::InvalidFieldValue { + packet: "GrandGrandChild", + field: "baz", + expected: "Enum16::A", + actual: format!("{:?}", parent.baz()), + }); + } + let payload = buf.to_vec(); + buf.advance(payload.len()); + let payload = Vec::from(payload); + if buf.is_empty() { + Ok(Self { payload }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn quux(&self) -> Enum16 { + Enum16::A + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } + pub fn bar(&self) -> Enum16 { + Enum16::A + } + pub fn baz(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for GrandGrandChild { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(u16::from(self.foo())); + buf.put_u16_le(u16::from(self.bar())); + buf.put_u16_le(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + buf.put_u16_le(u16::from(self.quux())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = GrandChild::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/generated/custom_field_declaration_big_endian.rs b/tests/generated/rust_legacy/custom_field_declaration_big_endian.rs index eb70e2f..79810e9 100644 --- a/tests/generated/custom_field_declaration_big_endian.rs +++ b/tests/generated/rust_legacy/custom_field_declaration_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(from = "u32", into = "u32"))] @@ -53,7 +58,7 @@ impl From<TruncatedSize> for u32 { } impl TryFrom<u32> for TruncatedSize { type Error = u32; - fn try_from(value: u32) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u32) -> Result<Self, Self::Error> { if value > 0xff_ffff { Err(value) } else { Ok(TruncatedSize(value)) } } } diff --git a/tests/generated/custom_field_declaration_little_endian.rs b/tests/generated/rust_legacy/custom_field_declaration_little_endian.rs index eb70e2f..79810e9 100644 --- a/tests/generated/custom_field_declaration_little_endian.rs +++ b/tests/generated/rust_legacy/custom_field_declaration_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(from = "u32", into = "u32"))] @@ -53,7 +58,7 @@ impl From<TruncatedSize> for u32 { } impl TryFrom<u32> for TruncatedSize { type Error = u32; - fn try_from(value: u32) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u32) -> Result<Self, Self::Error> { if value > 0xff_ffff { Err(value) } else { Ok(TruncatedSize(value)) } } } diff --git a/tests/generated/rust_legacy/enum_declaration_big_endian.rs b/tests/generated/rust_legacy/enum_declaration_big_endian.rs new file mode 100644 index 0000000..dcff08e --- /dev/null +++ b/tests/generated/rust_legacy/enum_declaration_big_endian.rs @@ -0,0 +1,521 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[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 { + A = 0x0, + B = 0x1, +} +impl TryFrom<u8> for IncompleteTruncatedClosed { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x0 => Ok(IncompleteTruncatedClosed::A), + 0x1 => Ok(IncompleteTruncatedClosed::B), + _ => Err(value), + } + } +} +impl From<&IncompleteTruncatedClosed> for u8 { + fn from(value: &IncompleteTruncatedClosed) -> Self { + match value { + IncompleteTruncatedClosed::A => 0x0, + IncompleteTruncatedClosed::B => 0x1, + } + } +} +impl From<IncompleteTruncatedClosed> for u8 { + fn from(value: IncompleteTruncatedClosed) -> Self { + (&value).into() + } +} +impl From<IncompleteTruncatedClosed> for i8 { + fn from(value: IncompleteTruncatedClosed) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedClosed> for i16 { + fn from(value: IncompleteTruncatedClosed) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedClosed> for i32 { + fn from(value: IncompleteTruncatedClosed) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedClosed> for i64 { + fn from(value: IncompleteTruncatedClosed) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedClosed> for u16 { + fn from(value: IncompleteTruncatedClosed) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedClosed> for u32 { + fn from(value: IncompleteTruncatedClosed) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedClosed> for u64 { + fn from(value: IncompleteTruncatedClosed) -> 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) -> 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) -> 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 { + A, + X, + Y, + B(Private<u8>), + Unknown(Private<u8>), +} +impl TryFrom<u8> for IncompleteTruncatedOpenWithRange { + type Error = u8; + fn try_from(value: u8) -> 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))), + _ => Err(value), + } + } +} +impl From<&IncompleteTruncatedOpenWithRange> for u8 { + fn from(value: &IncompleteTruncatedOpenWithRange) -> Self { + match value { + IncompleteTruncatedOpenWithRange::A => 0x0, + IncompleteTruncatedOpenWithRange::X => 0x1, + IncompleteTruncatedOpenWithRange::Y => 0x2, + IncompleteTruncatedOpenWithRange::B(Private(value)) => *value, + IncompleteTruncatedOpenWithRange::Unknown(Private(value)) => *value, + } + } +} +impl From<IncompleteTruncatedOpenWithRange> for u8 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + (&value).into() + } +} +impl From<IncompleteTruncatedOpenWithRange> for i8 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedOpenWithRange> for i16 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedOpenWithRange> for i32 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedOpenWithRange> for i64 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedOpenWithRange> for u16 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedOpenWithRange> for u32 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedOpenWithRange> for u64 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + u8::from(value) as Self + } +} +#[repr(u64)] +#[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 CompleteTruncated { + A = 0x0, + B = 0x1, + C = 0x2, + D = 0x3, + E = 0x4, + F = 0x5, + G = 0x6, + H = 0x7, +} +impl TryFrom<u8> for CompleteTruncated { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x0 => Ok(CompleteTruncated::A), + 0x1 => Ok(CompleteTruncated::B), + 0x2 => Ok(CompleteTruncated::C), + 0x3 => Ok(CompleteTruncated::D), + 0x4 => Ok(CompleteTruncated::E), + 0x5 => Ok(CompleteTruncated::F), + 0x6 => Ok(CompleteTruncated::G), + 0x7 => Ok(CompleteTruncated::H), + _ => Err(value), + } + } +} +impl From<&CompleteTruncated> for u8 { + fn from(value: &CompleteTruncated) -> Self { + match value { + CompleteTruncated::A => 0x0, + CompleteTruncated::B => 0x1, + CompleteTruncated::C => 0x2, + CompleteTruncated::D => 0x3, + CompleteTruncated::E => 0x4, + CompleteTruncated::F => 0x5, + CompleteTruncated::G => 0x6, + CompleteTruncated::H => 0x7, + } + } +} +impl From<CompleteTruncated> for u8 { + fn from(value: CompleteTruncated) -> Self { + (&value).into() + } +} +impl From<CompleteTruncated> for i8 { + fn from(value: CompleteTruncated) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncated> for i16 { + fn from(value: CompleteTruncated) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncated> for i32 { + fn from(value: CompleteTruncated) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncated> for i64 { + fn from(value: CompleteTruncated) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncated> for u16 { + fn from(value: CompleteTruncated) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncated> for u32 { + fn from(value: CompleteTruncated) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncated> for u64 { + fn from(value: CompleteTruncated) -> 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 CompleteTruncatedWithRange { + A, + X, + Y, + B(Private<u8>), +} +impl TryFrom<u8> for CompleteTruncatedWithRange { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x0 => Ok(CompleteTruncatedWithRange::A), + 0x1 => Ok(CompleteTruncatedWithRange::X), + 0x2 => Ok(CompleteTruncatedWithRange::Y), + 0x1..=0x7 => Ok(CompleteTruncatedWithRange::B(Private(value))), + _ => Err(value), + } + } +} +impl From<&CompleteTruncatedWithRange> for u8 { + fn from(value: &CompleteTruncatedWithRange) -> Self { + match value { + CompleteTruncatedWithRange::A => 0x0, + CompleteTruncatedWithRange::X => 0x1, + CompleteTruncatedWithRange::Y => 0x2, + CompleteTruncatedWithRange::B(Private(value)) => *value, + } + } +} +impl From<CompleteTruncatedWithRange> for u8 { + fn from(value: CompleteTruncatedWithRange) -> Self { + (&value).into() + } +} +impl From<CompleteTruncatedWithRange> for i8 { + fn from(value: CompleteTruncatedWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncatedWithRange> for i16 { + fn from(value: CompleteTruncatedWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncatedWithRange> for i32 { + fn from(value: CompleteTruncatedWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncatedWithRange> for i64 { + fn from(value: CompleteTruncatedWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncatedWithRange> for u16 { + fn from(value: CompleteTruncatedWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncatedWithRange> for u32 { + fn from(value: CompleteTruncatedWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncatedWithRange> for u64 { + fn from(value: CompleteTruncatedWithRange) -> 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 CompleteWithRange { + A, + B, + C(Private<u8>), +} +impl TryFrom<u8> for CompleteWithRange { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x0 => Ok(CompleteWithRange::A), + 0x1 => Ok(CompleteWithRange::B), + 0x2..=0xff => Ok(CompleteWithRange::C(Private(value))), + } + } +} +impl From<&CompleteWithRange> for u8 { + fn from(value: &CompleteWithRange) -> Self { + match value { + CompleteWithRange::A => 0x0, + CompleteWithRange::B => 0x1, + CompleteWithRange::C(Private(value)) => *value, + } + } +} +impl From<CompleteWithRange> for u8 { + fn from(value: CompleteWithRange) -> Self { + (&value).into() + } +} +impl From<CompleteWithRange> for i16 { + fn from(value: CompleteWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteWithRange> for i32 { + fn from(value: CompleteWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteWithRange> for i64 { + fn from(value: CompleteWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteWithRange> for u16 { + fn from(value: CompleteWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteWithRange> for u32 { + fn from(value: CompleteWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteWithRange> for u64 { + fn from(value: CompleteWithRange) -> Self { + u8::from(value) as Self + } +} diff --git a/tests/generated/rust_legacy/enum_declaration_little_endian.rs b/tests/generated/rust_legacy/enum_declaration_little_endian.rs new file mode 100644 index 0000000..dcff08e --- /dev/null +++ b/tests/generated/rust_legacy/enum_declaration_little_endian.rs @@ -0,0 +1,521 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[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 { + A = 0x0, + B = 0x1, +} +impl TryFrom<u8> for IncompleteTruncatedClosed { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x0 => Ok(IncompleteTruncatedClosed::A), + 0x1 => Ok(IncompleteTruncatedClosed::B), + _ => Err(value), + } + } +} +impl From<&IncompleteTruncatedClosed> for u8 { + fn from(value: &IncompleteTruncatedClosed) -> Self { + match value { + IncompleteTruncatedClosed::A => 0x0, + IncompleteTruncatedClosed::B => 0x1, + } + } +} +impl From<IncompleteTruncatedClosed> for u8 { + fn from(value: IncompleteTruncatedClosed) -> Self { + (&value).into() + } +} +impl From<IncompleteTruncatedClosed> for i8 { + fn from(value: IncompleteTruncatedClosed) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedClosed> for i16 { + fn from(value: IncompleteTruncatedClosed) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedClosed> for i32 { + fn from(value: IncompleteTruncatedClosed) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedClosed> for i64 { + fn from(value: IncompleteTruncatedClosed) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedClosed> for u16 { + fn from(value: IncompleteTruncatedClosed) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedClosed> for u32 { + fn from(value: IncompleteTruncatedClosed) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedClosed> for u64 { + fn from(value: IncompleteTruncatedClosed) -> 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) -> 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) -> 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 { + A, + X, + Y, + B(Private<u8>), + Unknown(Private<u8>), +} +impl TryFrom<u8> for IncompleteTruncatedOpenWithRange { + type Error = u8; + fn try_from(value: u8) -> 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))), + _ => Err(value), + } + } +} +impl From<&IncompleteTruncatedOpenWithRange> for u8 { + fn from(value: &IncompleteTruncatedOpenWithRange) -> Self { + match value { + IncompleteTruncatedOpenWithRange::A => 0x0, + IncompleteTruncatedOpenWithRange::X => 0x1, + IncompleteTruncatedOpenWithRange::Y => 0x2, + IncompleteTruncatedOpenWithRange::B(Private(value)) => *value, + IncompleteTruncatedOpenWithRange::Unknown(Private(value)) => *value, + } + } +} +impl From<IncompleteTruncatedOpenWithRange> for u8 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + (&value).into() + } +} +impl From<IncompleteTruncatedOpenWithRange> for i8 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedOpenWithRange> for i16 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedOpenWithRange> for i32 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedOpenWithRange> for i64 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedOpenWithRange> for u16 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedOpenWithRange> for u32 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<IncompleteTruncatedOpenWithRange> for u64 { + fn from(value: IncompleteTruncatedOpenWithRange) -> Self { + u8::from(value) as Self + } +} +#[repr(u64)] +#[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 CompleteTruncated { + A = 0x0, + B = 0x1, + C = 0x2, + D = 0x3, + E = 0x4, + F = 0x5, + G = 0x6, + H = 0x7, +} +impl TryFrom<u8> for CompleteTruncated { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x0 => Ok(CompleteTruncated::A), + 0x1 => Ok(CompleteTruncated::B), + 0x2 => Ok(CompleteTruncated::C), + 0x3 => Ok(CompleteTruncated::D), + 0x4 => Ok(CompleteTruncated::E), + 0x5 => Ok(CompleteTruncated::F), + 0x6 => Ok(CompleteTruncated::G), + 0x7 => Ok(CompleteTruncated::H), + _ => Err(value), + } + } +} +impl From<&CompleteTruncated> for u8 { + fn from(value: &CompleteTruncated) -> Self { + match value { + CompleteTruncated::A => 0x0, + CompleteTruncated::B => 0x1, + CompleteTruncated::C => 0x2, + CompleteTruncated::D => 0x3, + CompleteTruncated::E => 0x4, + CompleteTruncated::F => 0x5, + CompleteTruncated::G => 0x6, + CompleteTruncated::H => 0x7, + } + } +} +impl From<CompleteTruncated> for u8 { + fn from(value: CompleteTruncated) -> Self { + (&value).into() + } +} +impl From<CompleteTruncated> for i8 { + fn from(value: CompleteTruncated) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncated> for i16 { + fn from(value: CompleteTruncated) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncated> for i32 { + fn from(value: CompleteTruncated) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncated> for i64 { + fn from(value: CompleteTruncated) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncated> for u16 { + fn from(value: CompleteTruncated) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncated> for u32 { + fn from(value: CompleteTruncated) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncated> for u64 { + fn from(value: CompleteTruncated) -> 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 CompleteTruncatedWithRange { + A, + X, + Y, + B(Private<u8>), +} +impl TryFrom<u8> for CompleteTruncatedWithRange { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x0 => Ok(CompleteTruncatedWithRange::A), + 0x1 => Ok(CompleteTruncatedWithRange::X), + 0x2 => Ok(CompleteTruncatedWithRange::Y), + 0x1..=0x7 => Ok(CompleteTruncatedWithRange::B(Private(value))), + _ => Err(value), + } + } +} +impl From<&CompleteTruncatedWithRange> for u8 { + fn from(value: &CompleteTruncatedWithRange) -> Self { + match value { + CompleteTruncatedWithRange::A => 0x0, + CompleteTruncatedWithRange::X => 0x1, + CompleteTruncatedWithRange::Y => 0x2, + CompleteTruncatedWithRange::B(Private(value)) => *value, + } + } +} +impl From<CompleteTruncatedWithRange> for u8 { + fn from(value: CompleteTruncatedWithRange) -> Self { + (&value).into() + } +} +impl From<CompleteTruncatedWithRange> for i8 { + fn from(value: CompleteTruncatedWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncatedWithRange> for i16 { + fn from(value: CompleteTruncatedWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncatedWithRange> for i32 { + fn from(value: CompleteTruncatedWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncatedWithRange> for i64 { + fn from(value: CompleteTruncatedWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncatedWithRange> for u16 { + fn from(value: CompleteTruncatedWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncatedWithRange> for u32 { + fn from(value: CompleteTruncatedWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteTruncatedWithRange> for u64 { + fn from(value: CompleteTruncatedWithRange) -> 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 CompleteWithRange { + A, + B, + C(Private<u8>), +} +impl TryFrom<u8> for CompleteWithRange { + type Error = u8; + fn try_from(value: u8) -> Result<Self, Self::Error> { + match value { + 0x0 => Ok(CompleteWithRange::A), + 0x1 => Ok(CompleteWithRange::B), + 0x2..=0xff => Ok(CompleteWithRange::C(Private(value))), + } + } +} +impl From<&CompleteWithRange> for u8 { + fn from(value: &CompleteWithRange) -> Self { + match value { + CompleteWithRange::A => 0x0, + CompleteWithRange::B => 0x1, + CompleteWithRange::C(Private(value)) => *value, + } + } +} +impl From<CompleteWithRange> for u8 { + fn from(value: CompleteWithRange) -> Self { + (&value).into() + } +} +impl From<CompleteWithRange> for i16 { + fn from(value: CompleteWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteWithRange> for i32 { + fn from(value: CompleteWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteWithRange> for i64 { + fn from(value: CompleteWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteWithRange> for u16 { + fn from(value: CompleteWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteWithRange> for u32 { + fn from(value: CompleteWithRange) -> Self { + u8::from(value) as Self + } +} +impl From<CompleteWithRange> for u64 { + fn from(value: CompleteWithRange) -> Self { + u8::from(value) as Self + } +} diff --git a/tests/generated/packet_decl_24bit_enum_array_big_endian.rs b/tests/generated/rust_legacy/packet_decl_24bit_enum_array_big_endian.rs index d1bba97..d2b9d2f 100644 --- a/tests/generated/packet_decl_24bit_enum_array_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_24bit_enum_array_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Foo { } impl TryFrom<u32> for Foo { type Error = u32; - fn try_from(value: u32) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u32) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Foo::FooBar), 0x2 => Ok(Foo::Baz), @@ -84,15 +89,15 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 15 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 * 3 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 5 * 3, got: bytes.get().remaining(), }); @@ -100,22 +105,23 @@ impl BarData { let x = (0..5) .map(|_| { Foo::try_from(bytes.get_mut().get_uint(3) as u32) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Bar".to_string(), - field: String::new(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "", value: unknown_val as u64, - type_: "Foo".to_string(), + type_: "Foo", }) }) - .collect::<Result<Vec<_>>>()? + .collect::<Result<Vec<_>, DecodeError>>()? .try_into() - .map_err(|_| Error::InvalidPacketError)?; + .map_err(|_| DecodeError::InvalidPacketError)?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { for elem in &self.x { buffer.put_uint(u32::from(elem) as u64, 3); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -125,42 +131,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> &[Foo; 5] { &self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_24bit_enum_array_little_endian.rs b/tests/generated/rust_legacy/packet_decl_24bit_enum_array_little_endian.rs index 9a48b4b..c7e2ba2 100644 --- a/tests/generated/packet_decl_24bit_enum_array_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_24bit_enum_array_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Foo { } impl TryFrom<u32> for Foo { type Error = u32; - fn try_from(value: u32) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u32) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Foo::FooBar), 0x2 => Ok(Foo::Baz), @@ -84,15 +89,15 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 15 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 * 3 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 5 * 3, got: bytes.get().remaining(), }); @@ -100,22 +105,23 @@ 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 { - obj: "Bar".to_string(), - field: String::new(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "", value: unknown_val as u64, - type_: "Foo".to_string(), + type_: "Foo", }) }) - .collect::<Result<Vec<_>>>()? + .collect::<Result<Vec<_>, DecodeError>>()? .try_into() - .map_err(|_| Error::InvalidPacketError)?; + .map_err(|_| DecodeError::InvalidPacketError)?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { for elem in &self.x { buffer.put_uint_le(u32::from(elem) as u64, 3); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -125,42 +131,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> &[Foo; 5] { &self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_24bit_enum_big_endian.rs b/tests/generated/rust_legacy/packet_decl_24bit_enum_big_endian.rs index 64b6a81..38a7066 100644 --- a/tests/generated/packet_decl_24bit_enum_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_24bit_enum_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Foo { } impl TryFrom<u32> for Foo { type Error = u32; - fn try_from(value: u32) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u32) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Foo::A), 0x2 => Ok(Foo::B), @@ -84,30 +89,31 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 3 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 3, got: bytes.get().remaining(), }); } let x = Foo::try_from(bytes.get_mut().get_uint(3) as u32) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Bar".to_string(), - field: "x".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "x", value: unknown_val as u64, - type_: "Foo".to_string(), + type_: "Foo", })?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_uint(u32::from(self.x) as u64, 3); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -117,42 +123,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> Foo { self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_24bit_enum_little_endian.rs b/tests/generated/rust_legacy/packet_decl_24bit_enum_little_endian.rs index cd916a7..0a0818b 100644 --- a/tests/generated/packet_decl_24bit_enum_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_24bit_enum_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Foo { } impl TryFrom<u32> for Foo { type Error = u32; - fn try_from(value: u32) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u32) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Foo::A), 0x2 => Ok(Foo::B), @@ -84,30 +89,31 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 3 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 3, got: bytes.get().remaining(), }); } let x = Foo::try_from(bytes.get_mut().get_uint_le(3) as u32) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Bar".to_string(), - field: "x".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "x", value: unknown_val as u64, - type_: "Foo".to_string(), + type_: "Foo", })?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_uint_le(u32::from(self.x) as u64, 3); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -117,42 +123,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> Foo { self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_24bit_scalar_array_big_endian.rs b/tests/generated/rust_legacy/packet_decl_24bit_scalar_array_big_endian.rs index a0a810a..53692ce 100644 --- a/tests/generated/packet_decl_24bit_scalar_array_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_24bit_scalar_array_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -38,30 +43,31 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 15 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 * 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 5 * 3, got: bytes.get().remaining(), }); } let x = (0..5) - .map(|_| Ok::<_, Error>(bytes.get_mut().get_uint(3) as u32)) - .collect::<Result<Vec<_>>>()? + .map(|_| Ok::<_, DecodeError>(bytes.get_mut().get_uint(3) as u32)) + .collect::<Result<Vec<_>, DecodeError>>()? .try_into() - .map_err(|_| Error::InvalidPacketError)?; + .map_err(|_| DecodeError::InvalidPacketError)?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { for elem in &self.x { buffer.put_uint(*elem as u64, 3); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -71,42 +77,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_x(&self) -> &[u32; 5] { &self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_24bit_scalar_array_little_endian.rs b/tests/generated/rust_legacy/packet_decl_24bit_scalar_array_little_endian.rs index adbdff4..69758a1 100644 --- a/tests/generated/packet_decl_24bit_scalar_array_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_24bit_scalar_array_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -38,30 +43,31 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 15 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 * 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 5 * 3, got: bytes.get().remaining(), }); } let x = (0..5) - .map(|_| Ok::<_, Error>(bytes.get_mut().get_uint_le(3) as u32)) - .collect::<Result<Vec<_>>>()? + .map(|_| Ok::<_, DecodeError>(bytes.get_mut().get_uint_le(3) as u32)) + .collect::<Result<Vec<_>, DecodeError>>()? .try_into() - .map_err(|_| Error::InvalidPacketError)?; + .map_err(|_| DecodeError::InvalidPacketError)?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { for elem in &self.x { buffer.put_uint_le(*elem as u64, 3); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -71,42 +77,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_x(&self) -> &[u32; 5] { &self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_24bit_scalar_big_endian.rs b/tests/generated/rust_legacy/packet_decl_24bit_scalar_big_endian.rs index 2bbdde0..45b5b29 100644 --- a/tests/generated/packet_decl_24bit_scalar_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_24bit_scalar_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -38,15 +43,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 3 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); @@ -54,11 +59,17 @@ impl FooData { let x = bytes.get_mut().get_uint(3) as u32; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.x > 0xff_ffff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "x", self.x, 0xff_ffff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "x", + value: self.x as u64, + maximum_value: 0xff_ffff, + }); } buffer.put_uint(self.x as u64, 3); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -68,42 +79,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_x(&self) -> u32 { self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_24bit_scalar_little_endian.rs b/tests/generated/rust_legacy/packet_decl_24bit_scalar_little_endian.rs index fce2122..04e6057 100644 --- a/tests/generated/packet_decl_24bit_scalar_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_24bit_scalar_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -38,15 +43,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 3 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); @@ -54,11 +59,17 @@ impl FooData { let x = bytes.get_mut().get_uint_le(3) as u32; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.x > 0xff_ffff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "x", self.x, 0xff_ffff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "x", + value: self.x as u64, + maximum_value: 0xff_ffff, + }); } buffer.put_uint_le(self.x as u64, 3); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -68,42 +79,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_x(&self) -> u32 { self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_64bit_enum_array_big_endian.rs b/tests/generated/rust_legacy/packet_decl_64bit_enum_array_big_endian.rs index fce2ae1..d0a6e8f 100644 --- a/tests/generated/packet_decl_64bit_enum_array_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_64bit_enum_array_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Foo { } impl TryFrom<u64> for Foo { type Error = u64; - fn try_from(value: u64) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u64) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Foo::FooBar), 0x2 => Ok(Foo::Baz), @@ -69,15 +74,15 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 56 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 7 * 8 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 7 * 8, got: bytes.get().remaining(), }); @@ -85,22 +90,23 @@ impl BarData { let x = (0..7) .map(|_| { Foo::try_from(bytes.get_mut().get_u64()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Bar".to_string(), - field: String::new(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "", value: unknown_val as u64, - type_: "Foo".to_string(), + type_: "Foo", }) }) - .collect::<Result<Vec<_>>>()? + .collect::<Result<Vec<_>, DecodeError>>()? .try_into() - .map_err(|_| Error::InvalidPacketError)?; + .map_err(|_| DecodeError::InvalidPacketError)?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { for elem in &self.x { buffer.put_u64(u64::from(elem)); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -110,42 +116,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> &[Foo; 7] { &self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_64bit_enum_array_little_endian.rs b/tests/generated/rust_legacy/packet_decl_64bit_enum_array_little_endian.rs index 8d7c2a1..e8fd91f 100644 --- a/tests/generated/packet_decl_64bit_enum_array_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_64bit_enum_array_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Foo { } impl TryFrom<u64> for Foo { type Error = u64; - fn try_from(value: u64) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u64) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Foo::FooBar), 0x2 => Ok(Foo::Baz), @@ -69,15 +74,15 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 56 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 7 * 8 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 7 * 8, got: bytes.get().remaining(), }); @@ -85,22 +90,23 @@ impl BarData { let x = (0..7) .map(|_| { Foo::try_from(bytes.get_mut().get_u64_le()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Bar".to_string(), - field: String::new(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "", value: unknown_val as u64, - type_: "Foo".to_string(), + type_: "Foo", }) }) - .collect::<Result<Vec<_>>>()? + .collect::<Result<Vec<_>, DecodeError>>()? .try_into() - .map_err(|_| Error::InvalidPacketError)?; + .map_err(|_| DecodeError::InvalidPacketError)?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { for elem in &self.x { buffer.put_u64_le(u64::from(elem)); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -110,42 +116,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> &[Foo; 7] { &self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_64bit_enum_big_endian.rs b/tests/generated/rust_legacy/packet_decl_64bit_enum_big_endian.rs index 2a0c784..b1bd38b 100644 --- a/tests/generated/packet_decl_64bit_enum_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_64bit_enum_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Foo { } impl TryFrom<u64> for Foo { type Error = u64; - fn try_from(value: u64) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u64) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Foo::A), 0x2 => Ok(Foo::B), @@ -69,30 +74,31 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 8 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 8 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 8, got: bytes.get().remaining(), }); } let x = Foo::try_from(bytes.get_mut().get_u64()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Bar".to_string(), - field: "x".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "x", value: unknown_val as u64, - type_: "Foo".to_string(), + type_: "Foo", })?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u64(u64::from(self.x)); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -102,42 +108,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> Foo { self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_64bit_enum_little_endian.rs b/tests/generated/rust_legacy/packet_decl_64bit_enum_little_endian.rs index 0fcaa48..a472b7f 100644 --- a/tests/generated/packet_decl_64bit_enum_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_64bit_enum_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Foo { } impl TryFrom<u64> for Foo { type Error = u64; - fn try_from(value: u64) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u64) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Foo::A), 0x2 => Ok(Foo::B), @@ -69,30 +74,31 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 8 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 8 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 8, got: bytes.get().remaining(), }); } let x = Foo::try_from(bytes.get_mut().get_u64_le()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Bar".to_string(), - field: "x".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "x", value: unknown_val as u64, - type_: "Foo".to_string(), + type_: "Foo", })?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u64_le(u64::from(self.x)); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -102,42 +108,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> Foo { self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_64bit_scalar_array_big_endian.rs b/tests/generated/rust_legacy/packet_decl_64bit_scalar_array_big_endian.rs index 261e4dd..83d690e 100644 --- a/tests/generated/packet_decl_64bit_scalar_array_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_64bit_scalar_array_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -38,30 +43,31 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 56 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 7 * 8 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 7 * 8, got: bytes.get().remaining(), }); } let x = (0..7) - .map(|_| Ok::<_, Error>(bytes.get_mut().get_u64())) - .collect::<Result<Vec<_>>>()? + .map(|_| Ok::<_, DecodeError>(bytes.get_mut().get_u64())) + .collect::<Result<Vec<_>, DecodeError>>()? .try_into() - .map_err(|_| Error::InvalidPacketError)?; + .map_err(|_| DecodeError::InvalidPacketError)?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { for elem in &self.x { buffer.put_u64(*elem); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -71,42 +77,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_x(&self) -> &[u64; 7] { &self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_64bit_scalar_array_little_endian.rs b/tests/generated/rust_legacy/packet_decl_64bit_scalar_array_little_endian.rs index f60c64c..85b05df 100644 --- a/tests/generated/packet_decl_64bit_scalar_array_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_64bit_scalar_array_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -38,30 +43,31 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 56 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 7 * 8 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 7 * 8, got: bytes.get().remaining(), }); } let x = (0..7) - .map(|_| Ok::<_, Error>(bytes.get_mut().get_u64_le())) - .collect::<Result<Vec<_>>>()? + .map(|_| Ok::<_, DecodeError>(bytes.get_mut().get_u64_le())) + .collect::<Result<Vec<_>, DecodeError>>()? .try_into() - .map_err(|_| Error::InvalidPacketError)?; + .map_err(|_| DecodeError::InvalidPacketError)?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { for elem in &self.x { buffer.put_u64_le(*elem); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -71,42 +77,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_x(&self) -> &[u64; 7] { &self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_64bit_scalar_big_endian.rs b/tests/generated/rust_legacy/packet_decl_64bit_scalar_big_endian.rs index e067fac..2d3e07d 100644 --- a/tests/generated/packet_decl_64bit_scalar_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_64bit_scalar_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -38,15 +43,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 8 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 8 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 8, got: bytes.get().remaining(), }); @@ -54,8 +59,9 @@ impl FooData { let x = bytes.get_mut().get_u64(); Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u64(self.x); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -65,42 +71,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_x(&self) -> u64 { self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_64bit_scalar_little_endian.rs b/tests/generated/rust_legacy/packet_decl_64bit_scalar_little_endian.rs index 815d0b1..37bf6bd 100644 --- a/tests/generated/packet_decl_64bit_scalar_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_64bit_scalar_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -38,15 +43,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 8 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 8 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 8, got: bytes.get().remaining(), }); @@ -54,8 +59,9 @@ impl FooData { let x = bytes.get_mut().get_u64_le(); Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u64_le(self.x); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -65,42 +71,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_x(&self) -> u64 { self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_8bit_enum_array_big_endian.rs b/tests/generated/rust_legacy/packet_decl_8bit_enum_array_big_endian.rs index ba959a6..4af419c 100644 --- a/tests/generated/packet_decl_8bit_enum_array_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_8bit_enum_array_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Foo { } impl TryFrom<u8> for Foo { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Foo::FooBar), 0x2 => Ok(Foo::Baz), @@ -99,15 +104,15 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 3 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 3, got: bytes.get().remaining(), }); @@ -115,22 +120,23 @@ impl BarData { let x = (0..3) .map(|_| { Foo::try_from(bytes.get_mut().get_u8()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Bar".to_string(), - field: String::new(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "", value: unknown_val as u64, - type_: "Foo".to_string(), + type_: "Foo", }) }) - .collect::<Result<Vec<_>>>()? + .collect::<Result<Vec<_>, DecodeError>>()? .try_into() - .map_err(|_| Error::InvalidPacketError)?; + .map_err(|_| DecodeError::InvalidPacketError)?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { for elem in &self.x { buffer.put_u8(u8::from(elem)); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -140,42 +146,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> &[Foo; 3] { &self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_8bit_enum_array_little_endian.rs b/tests/generated/rust_legacy/packet_decl_8bit_enum_array_little_endian.rs index ba959a6..4af419c 100644 --- a/tests/generated/packet_decl_8bit_enum_array_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_8bit_enum_array_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Foo { } impl TryFrom<u8> for Foo { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Foo::FooBar), 0x2 => Ok(Foo::Baz), @@ -99,15 +104,15 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 3 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 3, got: bytes.get().remaining(), }); @@ -115,22 +120,23 @@ impl BarData { let x = (0..3) .map(|_| { Foo::try_from(bytes.get_mut().get_u8()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Bar".to_string(), - field: String::new(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "", value: unknown_val as u64, - type_: "Foo".to_string(), + type_: "Foo", }) }) - .collect::<Result<Vec<_>>>()? + .collect::<Result<Vec<_>, DecodeError>>()? .try_into() - .map_err(|_| Error::InvalidPacketError)?; + .map_err(|_| DecodeError::InvalidPacketError)?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { for elem in &self.x { buffer.put_u8(u8::from(elem)); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -140,42 +146,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> &[Foo; 3] { &self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_8bit_enum_big_endian.rs b/tests/generated/rust_legacy/packet_decl_8bit_enum_big_endian.rs index 03bec5d..3278fb5 100644 --- a/tests/generated/packet_decl_8bit_enum_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_8bit_enum_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Foo { } impl TryFrom<u8> for Foo { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Foo::A), 0x2 => Ok(Foo::B), @@ -99,30 +104,31 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 1, got: bytes.get().remaining(), }); } let x = Foo::try_from(bytes.get_mut().get_u8()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Bar".to_string(), - field: "x".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "x", value: unknown_val as u64, - type_: "Foo".to_string(), + type_: "Foo", })?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(u8::from(self.x)); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -132,42 +138,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> Foo { self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_8bit_enum_little_endian.rs b/tests/generated/rust_legacy/packet_decl_8bit_enum_little_endian.rs index 03bec5d..3278fb5 100644 --- a/tests/generated/packet_decl_8bit_enum_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_8bit_enum_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Foo { } impl TryFrom<u8> for Foo { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Foo::A), 0x2 => Ok(Foo::B), @@ -99,30 +104,31 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 1, got: bytes.get().remaining(), }); } let x = Foo::try_from(bytes.get_mut().get_u8()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Bar".to_string(), - field: "x".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Bar", + field: "x", value: unknown_val as u64, - type_: "Foo".to_string(), + type_: "Foo", })?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(u8::from(self.x)); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -132,42 +138,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> Foo { self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_8bit_scalar_array_big_endian.rs b/tests/generated/rust_legacy/packet_decl_8bit_scalar_array_big_endian.rs index 74099b0..4cbe85e 100644 --- a/tests/generated/packet_decl_8bit_scalar_array_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_8bit_scalar_array_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -38,30 +43,31 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 3 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); } let x = (0..3) - .map(|_| Ok::<_, Error>(bytes.get_mut().get_u8())) - .collect::<Result<Vec<_>>>()? + .map(|_| Ok::<_, DecodeError>(bytes.get_mut().get_u8())) + .collect::<Result<Vec<_>, DecodeError>>()? .try_into() - .map_err(|_| Error::InvalidPacketError)?; + .map_err(|_| DecodeError::InvalidPacketError)?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { for elem in &self.x { buffer.put_u8(*elem); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -71,42 +77,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_x(&self) -> &[u8; 3] { &self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_8bit_scalar_array_little_endian.rs b/tests/generated/rust_legacy/packet_decl_8bit_scalar_array_little_endian.rs index 74099b0..4cbe85e 100644 --- a/tests/generated/packet_decl_8bit_scalar_array_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_8bit_scalar_array_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -38,30 +43,31 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 3 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); } let x = (0..3) - .map(|_| Ok::<_, Error>(bytes.get_mut().get_u8())) - .collect::<Result<Vec<_>>>()? + .map(|_| Ok::<_, DecodeError>(bytes.get_mut().get_u8())) + .collect::<Result<Vec<_>, DecodeError>>()? .try_into() - .map_err(|_| Error::InvalidPacketError)?; + .map_err(|_| DecodeError::InvalidPacketError)?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { for elem in &self.x { buffer.put_u8(*elem); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -71,42 +77,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_x(&self) -> &[u8; 3] { &self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_8bit_scalar_big_endian.rs b/tests/generated/rust_legacy/packet_decl_8bit_scalar_big_endian.rs index de13f31..27089b2 100644 --- a/tests/generated/packet_decl_8bit_scalar_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_8bit_scalar_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -38,15 +43,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); @@ -54,8 +59,9 @@ impl FooData { let x = bytes.get_mut().get_u8(); Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(self.x); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -65,42 +71,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_x(&self) -> u8 { self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_8bit_scalar_little_endian.rs b/tests/generated/rust_legacy/packet_decl_8bit_scalar_little_endian.rs index de13f31..27089b2 100644 --- a/tests/generated/packet_decl_8bit_scalar_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_8bit_scalar_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -38,15 +43,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); @@ -54,8 +59,9 @@ impl FooData { let x = bytes.get_mut().get_u8(); Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(self.x); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -65,42 +71,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_x(&self) -> u8 { self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_array_dynamic_count_big_endian.rs b/tests/generated/rust_legacy/packet_decl_array_dynamic_count_big_endian.rs index 074443c..b8a5124 100644 --- a/tests/generated/packet_decl_array_dynamic_count_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_array_dynamic_count_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -40,15 +45,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); @@ -57,31 +62,40 @@ impl FooData { let x_count = (chunk & 0x1f) as usize; let padding = ((chunk >> 5) & 0x7); if bytes.get().remaining() < x_count * 3usize { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: x_count * 3usize, got: bytes.get().remaining(), }); } let x = (0..x_count) - .map(|_| Ok::<_, Error>(bytes.get_mut().get_uint(3) as u32)) - .collect::<Result<Vec<_>>>()?; + .map(|_| Ok::<_, DecodeError>(bytes.get_mut().get_uint(3) as u32)) + .collect::<Result<Vec<_>, DecodeError>>()?; Ok(Self { padding, x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.x.len() > 0x1f { - panic!("Invalid length for {}::{}: {} > {}", "Foo", "x", self.x.len(), 0x1f); + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "x", + count: self.x.len(), + maximum_count: 0x1f, + }); } if self.padding > 0x7 { - panic!( - "Invalid value for {}::{}: {} > {}", "Foo", "padding", self.padding, 0x7 - ); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "padding", + value: self.padding as u64, + maximum_value: 0x7, + }); } let value = self.x.len() as u8 | (self.padding << 5); buffer.put_u8(value); for elem in &self.x { buffer.put_uint(*elem as u64, 3); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -91,36 +105,39 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_padding(&self) -> u8 { @@ -129,7 +146,7 @@ impl Foo { pub fn get_x(&self) -> &Vec<u32> { &self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_array_dynamic_count_little_endian.rs b/tests/generated/rust_legacy/packet_decl_array_dynamic_count_little_endian.rs index e6429b4..dd02c56 100644 --- a/tests/generated/packet_decl_array_dynamic_count_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_array_dynamic_count_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -40,15 +45,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); @@ -57,31 +62,40 @@ impl FooData { let x_count = (chunk & 0x1f) as usize; let padding = ((chunk >> 5) & 0x7); if bytes.get().remaining() < x_count * 3usize { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: x_count * 3usize, got: bytes.get().remaining(), }); } let x = (0..x_count) - .map(|_| Ok::<_, Error>(bytes.get_mut().get_uint_le(3) as u32)) - .collect::<Result<Vec<_>>>()?; + .map(|_| Ok::<_, DecodeError>(bytes.get_mut().get_uint_le(3) as u32)) + .collect::<Result<Vec<_>, DecodeError>>()?; Ok(Self { padding, x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.x.len() > 0x1f { - panic!("Invalid length for {}::{}: {} > {}", "Foo", "x", self.x.len(), 0x1f); + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "x", + count: self.x.len(), + maximum_count: 0x1f, + }); } if self.padding > 0x7 { - panic!( - "Invalid value for {}::{}: {} > {}", "Foo", "padding", self.padding, 0x7 - ); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "padding", + value: self.padding as u64, + maximum_value: 0x7, + }); } let value = self.x.len() as u8 | (self.padding << 5); buffer.put_u8(value); for elem in &self.x { buffer.put_uint_le(*elem as u64, 3); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -91,36 +105,39 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_padding(&self) -> u8 { @@ -129,7 +146,7 @@ impl Foo { pub fn get_x(&self) -> &Vec<u32> { &self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_array_dynamic_size_big_endian.rs b/tests/generated/rust_legacy/packet_decl_array_dynamic_size_big_endian.rs index a4899a1..3616fe5 100644 --- a/tests/generated/packet_decl_array_dynamic_size_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_array_dynamic_size_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -40,15 +45,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); @@ -57,14 +62,14 @@ impl FooData { let x_size = (chunk & 0x1f) as usize; let padding = ((chunk >> 5) & 0x7); if bytes.get().remaining() < x_size { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: x_size, got: bytes.get().remaining(), }); } if x_size % 3 != 0 { - return Err(Error::InvalidArraySize { + return Err(DecodeError::InvalidArraySize { array: x_size, element: 3, }); @@ -72,27 +77,33 @@ impl FooData { let x_count = x_size / 3; let mut x = Vec::with_capacity(x_count); for _ in 0..x_count { - x.push(Ok::<_, Error>(bytes.get_mut().get_uint(3) as u32)?); + x.push(Ok::<_, DecodeError>(bytes.get_mut().get_uint(3) as u32)?); } Ok(Self { padding, x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if (self.x.len() * 3) > 0x1f { - panic!( - "Invalid length for {}::{}: {} > {}", "Foo", "x", (self.x.len() * 3), - 0x1f - ); + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "x", + size: (self.x.len() * 3), + maximum_size: 0x1f, + }); } if self.padding > 0x7 { - panic!( - "Invalid value for {}::{}: {} > {}", "Foo", "padding", self.padding, 0x7 - ); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "padding", + value: self.padding as u64, + maximum_value: 0x7, + }); } let value = (self.x.len() * 3) as u8 | (self.padding << 5); buffer.put_u8(value); for elem in &self.x { buffer.put_uint(*elem as u64, 3); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -102,36 +113,39 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_padding(&self) -> u8 { @@ -140,7 +154,7 @@ impl Foo { pub fn get_x(&self) -> &Vec<u32> { &self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_array_dynamic_size_little_endian.rs b/tests/generated/rust_legacy/packet_decl_array_dynamic_size_little_endian.rs index d048bfc..a5f3406 100644 --- a/tests/generated/packet_decl_array_dynamic_size_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_array_dynamic_size_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -40,15 +45,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); @@ -57,14 +62,14 @@ impl FooData { let x_size = (chunk & 0x1f) as usize; let padding = ((chunk >> 5) & 0x7); if bytes.get().remaining() < x_size { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: x_size, got: bytes.get().remaining(), }); } if x_size % 3 != 0 { - return Err(Error::InvalidArraySize { + return Err(DecodeError::InvalidArraySize { array: x_size, element: 3, }); @@ -72,27 +77,33 @@ impl FooData { let x_count = x_size / 3; let mut x = Vec::with_capacity(x_count); for _ in 0..x_count { - x.push(Ok::<_, Error>(bytes.get_mut().get_uint_le(3) as u32)?); + x.push(Ok::<_, DecodeError>(bytes.get_mut().get_uint_le(3) as u32)?); } Ok(Self { padding, x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if (self.x.len() * 3) > 0x1f { - panic!( - "Invalid length for {}::{}: {} > {}", "Foo", "x", (self.x.len() * 3), - 0x1f - ); + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "x", + size: (self.x.len() * 3), + maximum_size: 0x1f, + }); } if self.padding > 0x7 { - panic!( - "Invalid value for {}::{}: {} > {}", "Foo", "padding", self.padding, 0x7 - ); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "padding", + value: self.padding as u64, + maximum_value: 0x7, + }); } let value = (self.x.len() * 3) as u8 | (self.padding << 5); buffer.put_u8(value); for elem in &self.x { buffer.put_uint_le(*elem as u64, 3); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -102,36 +113,39 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_padding(&self) -> u8 { @@ -140,7 +154,7 @@ impl Foo { pub fn get_x(&self) -> &Vec<u32> { &self.foo.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_array_unknown_element_width_dynamic_count_big_endian.rs b/tests/generated/rust_legacy/packet_decl_array_unknown_element_width_dynamic_count_big_endian.rs index d542792..09ee1ca 100644 --- a/tests/generated/packet_decl_array_unknown_element_width_dynamic_count_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_array_unknown_element_width_dynamic_count_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Foo { @@ -27,43 +32,46 @@ impl Foo { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 5 } - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 5, got: bytes.get().remaining(), }); } let a_count = bytes.get_mut().get_uint(5) as usize; if bytes.get().remaining() < a_count * 2usize { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: a_count * 2usize, got: bytes.get().remaining(), }); } let a = (0..a_count) - .map(|_| Ok::<_, Error>(bytes.get_mut().get_u16())) - .collect::<Result<Vec<_>>>()?; + .map(|_| Ok::<_, DecodeError>(bytes.get_mut().get_u16())) + .collect::<Result<Vec<_>, DecodeError>>()?; Ok(Self { a }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.a.len() > 0xff_ffff_ffff_usize { - panic!( - "Invalid length for {}::{}: {} > {}", "Foo", "a", self.a.len(), - 0xff_ffff_ffff_usize - ); + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "a", + count: self.a.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); } buffer.put_uint(self.a.len() as u64, 5); for elem in &self.a { buffer.put_u16(*elem); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -92,15 +100,15 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 5 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 5, got: bytes.get().remaining(), }); @@ -108,20 +116,23 @@ impl BarData { let x_count = bytes.get_mut().get_uint(5) as usize; let x = (0..x_count) .map(|_| Foo::parse_inner(bytes)) - .collect::<Result<Vec<_>>>()?; + .collect::<Result<Vec<_>, DecodeError>>()?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.x.len() > 0xff_ffff_ffff_usize { - panic!( - "Invalid length for {}::{}: {} > {}", "Bar", "x", self.x.len(), - 0xff_ffff_ffff_usize - ); + return Err(EncodeError::CountOverflow { + packet: "Bar", + field: "x", + count: self.x.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); } buffer.put_uint(self.x.len() as u64, 5); for elem in &self.x { - elem.write_to(buffer); + elem.write_to(buffer)?; } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -131,42 +142,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> &Vec<Foo> { &self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_array_unknown_element_width_dynamic_count_little_endian.rs b/tests/generated/rust_legacy/packet_decl_array_unknown_element_width_dynamic_count_little_endian.rs index 767671f..81861ee 100644 --- a/tests/generated/packet_decl_array_unknown_element_width_dynamic_count_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_array_unknown_element_width_dynamic_count_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Foo { @@ -27,43 +32,46 @@ impl Foo { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 5 } - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 5, got: bytes.get().remaining(), }); } let a_count = bytes.get_mut().get_uint_le(5) as usize; if bytes.get().remaining() < a_count * 2usize { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: a_count * 2usize, got: bytes.get().remaining(), }); } let a = (0..a_count) - .map(|_| Ok::<_, Error>(bytes.get_mut().get_u16_le())) - .collect::<Result<Vec<_>>>()?; + .map(|_| Ok::<_, DecodeError>(bytes.get_mut().get_u16_le())) + .collect::<Result<Vec<_>, DecodeError>>()?; Ok(Self { a }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.a.len() > 0xff_ffff_ffff_usize { - panic!( - "Invalid length for {}::{}: {} > {}", "Foo", "a", self.a.len(), - 0xff_ffff_ffff_usize - ); + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "a", + count: self.a.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); } buffer.put_uint_le(self.a.len() as u64, 5); for elem in &self.a { buffer.put_u16_le(*elem); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -92,15 +100,15 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 5 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 5, got: bytes.get().remaining(), }); @@ -108,20 +116,23 @@ impl BarData { let x_count = bytes.get_mut().get_uint_le(5) as usize; let x = (0..x_count) .map(|_| Foo::parse_inner(bytes)) - .collect::<Result<Vec<_>>>()?; + .collect::<Result<Vec<_>, DecodeError>>()?; Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.x.len() > 0xff_ffff_ffff_usize { - panic!( - "Invalid length for {}::{}: {} > {}", "Bar", "x", self.x.len(), - 0xff_ffff_ffff_usize - ); + return Err(EncodeError::CountOverflow { + packet: "Bar", + field: "x", + count: self.x.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); } buffer.put_uint_le(self.x.len() as u64, 5); for elem in &self.x { - elem.write_to(buffer); + elem.write_to(buffer)?; } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -131,42 +142,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> &Vec<Foo> { &self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_array_unknown_element_width_dynamic_size_big_endian.rs b/tests/generated/rust_legacy/packet_decl_array_unknown_element_width_dynamic_size_big_endian.rs index 63d2dc2..c2e7884 100644 --- a/tests/generated/packet_decl_array_unknown_element_width_dynamic_size_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_array_unknown_element_width_dynamic_size_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Foo { @@ -27,43 +32,46 @@ impl Foo { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 5 } - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 5, got: bytes.get().remaining(), }); } let a_count = bytes.get_mut().get_uint(5) as usize; if bytes.get().remaining() < a_count * 2usize { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: a_count * 2usize, got: bytes.get().remaining(), }); } let a = (0..a_count) - .map(|_| Ok::<_, Error>(bytes.get_mut().get_u16())) - .collect::<Result<Vec<_>>>()?; + .map(|_| Ok::<_, DecodeError>(bytes.get_mut().get_u16())) + .collect::<Result<Vec<_>, DecodeError>>()?; Ok(Self { a }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.a.len() > 0xff_ffff_ffff_usize { - panic!( - "Invalid length for {}::{}: {} > {}", "Foo", "a", self.a.len(), - 0xff_ffff_ffff_usize - ); + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "a", + count: self.a.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); } buffer.put_uint(self.a.len() as u64, 5); for elem in &self.a { buffer.put_u16(*elem); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -92,23 +100,23 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 5 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 5, got: bytes.get().remaining(), }); } let x_size = bytes.get_mut().get_uint(5) as usize; if bytes.get().remaining() < x_size { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: x_size, got: bytes.get().remaining(), }); @@ -122,18 +130,21 @@ impl BarData { } Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { let x_size = self.x.iter().map(|elem| elem.get_size()).sum::<usize>(); if x_size > 0xff_ffff_ffff_usize { - panic!( - "Invalid length for {}::{}: {} > {}", "Bar", "x", x_size, - 0xff_ffff_ffff_usize - ); + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_size, + maximum_size: 0xff_ffff_ffff_usize, + }); } buffer.put_uint(x_size as u64, 5); for elem in &self.x { - elem.write_to(buffer); + elem.write_to(buffer)?; } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -143,42 +154,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> &Vec<Foo> { &self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_array_unknown_element_width_dynamic_size_little_endian.rs b/tests/generated/rust_legacy/packet_decl_array_unknown_element_width_dynamic_size_little_endian.rs index 30ef3ba..8c03cbf 100644 --- a/tests/generated/packet_decl_array_unknown_element_width_dynamic_size_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_array_unknown_element_width_dynamic_size_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Foo { @@ -27,43 +32,46 @@ impl Foo { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 5 } - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 5, got: bytes.get().remaining(), }); } let a_count = bytes.get_mut().get_uint_le(5) as usize; if bytes.get().remaining() < a_count * 2usize { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: a_count * 2usize, got: bytes.get().remaining(), }); } let a = (0..a_count) - .map(|_| Ok::<_, Error>(bytes.get_mut().get_u16_le())) - .collect::<Result<Vec<_>>>()?; + .map(|_| Ok::<_, DecodeError>(bytes.get_mut().get_u16_le())) + .collect::<Result<Vec<_>, DecodeError>>()?; Ok(Self { a }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.a.len() > 0xff_ffff_ffff_usize { - panic!( - "Invalid length for {}::{}: {} > {}", "Foo", "a", self.a.len(), - 0xff_ffff_ffff_usize - ); + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "a", + count: self.a.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); } buffer.put_uint_le(self.a.len() as u64, 5); for elem in &self.a { buffer.put_u16_le(*elem); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -92,23 +100,23 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 5 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 5, got: bytes.get().remaining(), }); } let x_size = bytes.get_mut().get_uint_le(5) as usize; if bytes.get().remaining() < x_size { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: x_size, got: bytes.get().remaining(), }); @@ -122,18 +130,21 @@ impl BarData { } Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { let x_size = self.x.iter().map(|elem| elem.get_size()).sum::<usize>(); if x_size > 0xff_ffff_ffff_usize { - panic!( - "Invalid length for {}::{}: {} > {}", "Bar", "x", x_size, - 0xff_ffff_ffff_usize - ); + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "x", + size: x_size, + maximum_size: 0xff_ffff_ffff_usize, + }); } buffer.put_uint_le(x_size as u64, 5); for elem in &self.x { - elem.write_to(buffer); + elem.write_to(buffer)?; } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -143,42 +154,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_x(&self) -> &Vec<Foo> { &self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_array_with_padding_big_endian.rs b/tests/generated/rust_legacy/packet_decl_array_with_padding_big_endian.rs index 0231b64..ed28697 100644 --- a/tests/generated/packet_decl_array_with_padding_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_array_with_padding_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Foo { @@ -27,43 +32,46 @@ impl Foo { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 5 } - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 5, got: bytes.get().remaining(), }); } let a_count = bytes.get_mut().get_uint(5) as usize; if bytes.get().remaining() < a_count * 2usize { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: a_count * 2usize, got: bytes.get().remaining(), }); } let a = (0..a_count) - .map(|_| Ok::<_, Error>(bytes.get_mut().get_u16())) - .collect::<Result<Vec<_>>>()?; + .map(|_| Ok::<_, DecodeError>(bytes.get_mut().get_u16())) + .collect::<Result<Vec<_>, DecodeError>>()?; Ok(Self { a }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.a.len() > 0xff_ffff_ffff_usize { - panic!( - "Invalid length for {}::{}: {} > {}", "Foo", "a", self.a.len(), - 0xff_ffff_ffff_usize - ); + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "a", + count: self.a.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); } buffer.put_uint(self.a.len() as u64, 5); for elem in &self.a { buffer.put_u16(*elem); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -92,15 +100,15 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 128 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 128usize { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 128usize, got: bytes.get().remaining(), }); @@ -114,18 +122,21 @@ impl BarData { } Ok(Self { a }) } - fn write_to(&self, buffer: &mut BytesMut) { - let current_size = buffer.len(); - for elem in &self.a { - elem.write_to(buffer); - } - let array_size = buffer.len() - current_size; + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { + let array_size = self.a.iter().fold(0, |size, elem| size + elem.get_size()); if array_size > 128usize { - panic!( - "attempted to serialize an array larger than the enclosing padding size" - ); + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "a", + size: array_size, + maximum_size: 128usize, + }); + } + for elem in &self.a { + elem.write_to(buffer)?; } buffer.put_bytes(0, 128usize - array_size); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -135,42 +146,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_a(&self) -> &Vec<Foo> { &self.bar.a } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_array_with_padding_little_endian.rs b/tests/generated/rust_legacy/packet_decl_array_with_padding_little_endian.rs index 6aee602..df72439 100644 --- a/tests/generated/packet_decl_array_with_padding_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_array_with_padding_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Foo { @@ -27,43 +32,46 @@ impl Foo { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 5 } - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 5, got: bytes.get().remaining(), }); } let a_count = bytes.get_mut().get_uint_le(5) as usize; if bytes.get().remaining() < a_count * 2usize { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: a_count * 2usize, got: bytes.get().remaining(), }); } let a = (0..a_count) - .map(|_| Ok::<_, Error>(bytes.get_mut().get_u16_le())) - .collect::<Result<Vec<_>>>()?; + .map(|_| Ok::<_, DecodeError>(bytes.get_mut().get_u16_le())) + .collect::<Result<Vec<_>, DecodeError>>()?; Ok(Self { a }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.a.len() > 0xff_ffff_ffff_usize { - panic!( - "Invalid length for {}::{}: {} > {}", "Foo", "a", self.a.len(), - 0xff_ffff_ffff_usize - ); + return Err(EncodeError::CountOverflow { + packet: "Foo", + field: "a", + count: self.a.len(), + maximum_count: 0xff_ffff_ffff_usize, + }); } buffer.put_uint_le(self.a.len() as u64, 5); for elem in &self.a { buffer.put_u16_le(*elem); } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -92,15 +100,15 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 128 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 128usize { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 128usize, got: bytes.get().remaining(), }); @@ -114,18 +122,21 @@ impl BarData { } Ok(Self { a }) } - fn write_to(&self, buffer: &mut BytesMut) { - let current_size = buffer.len(); - for elem in &self.a { - elem.write_to(buffer); - } - let array_size = buffer.len() - current_size; + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { + let array_size = self.a.iter().fold(0, |size, elem| size + elem.get_size()); if array_size > 128usize { - panic!( - "attempted to serialize an array larger than the enclosing padding size" - ); + return Err(EncodeError::SizeOverflow { + packet: "Bar", + field: "a", + size: array_size, + maximum_size: 128usize, + }); + } + for elem in &self.a { + elem.write_to(buffer)?; } buffer.put_bytes(0, 128usize - array_size); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -135,42 +146,45 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.bar.get_size()); - self.bar.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.bar.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = BarData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(bar: BarData) -> Result<Self> { + fn new(bar: BarData) -> Result<Self, DecodeError> { Ok(Self { bar }) } pub fn get_a(&self) -> &Vec<Foo> { &self.bar.a } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_child_packets_big_endian.rs b/tests/generated/rust_legacy/packet_decl_child_packets_big_endian.rs index 3498cae..3cb5980 100644 --- a/tests/generated/packet_decl_child_packets_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_child_packets_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Enum16 { } impl TryFrom<u16> for Enum16 { type Error = u16; - fn try_from(value: u16) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u16) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Enum16::A), 0x2 => Ok(Enum16::B), @@ -119,45 +124,45 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 4 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); } let a = bytes.get_mut().get_u8(); if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 2, got: bytes.get().remaining(), }); } let b = Enum16::try_from(bytes.get_mut().get_u16()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Foo".to_string(), - field: "b".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "b", value: unknown_val as u64, - type_: "Enum16".to_string(), + type_: "Enum16", })?; if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); } let payload_size = bytes.get_mut().get_u8() as usize; if bytes.get().remaining() < payload_size { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: payload_size, got: bytes.get().remaining(), }); @@ -182,22 +187,25 @@ impl FooData { }; Ok(Self { a, b, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(self.a); buffer.put_u16(u16::from(self.b)); if self.child.get_total_size() > 0xff { - panic!( - "Invalid length for {}::{}: {} > {}", "Foo", "_payload_", self.child - .get_total_size(), 0xff - ); + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: self.child.get_total_size(), + maximum_size: 0xff, + }); } buffer.put_u8(self.child.get_total_size() as u8); match &self.child { - FooDataChild::Bar(child) => child.write_to(buffer), - FooDataChild::Baz(child) => child.write_to(buffer), + FooDataChild::Bar(child) => child.write_to(buffer)?, + FooDataChild::Baz(child) => child.write_to(buffer)?, FooDataChild::Payload(payload) => buffer.put_slice(payload), FooDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -207,32 +215,35 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } @@ -244,7 +255,7 @@ impl Foo { FooDataChild::None => FooChild::None, } } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_a(&self) -> u8 { @@ -253,7 +264,7 @@ impl Foo { pub fn get_b(&self) -> Enum16 { self.foo.b } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -301,15 +312,15 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 1, got: bytes.get().remaining(), }); @@ -317,8 +328,9 @@ impl BarData { let x = bytes.get_mut().get_u8(); Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(self.x); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -328,23 +340,26 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<Bar> for Foo { @@ -353,26 +368,26 @@ impl From<Bar> for Foo { } } impl TryFrom<Foo> for Bar { - type Error = Error; - fn try_from(packet: Foo) -> Result<Bar> { + type Error = DecodeError; + fn try_from(packet: Foo) -> Result<Bar, Self::Error> { Bar::new(packet.foo) } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { let bar = match &foo.child { FooDataChild::Bar(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(FooDataChild::Bar), actual: format!("{:?}", & foo.child), }); @@ -389,7 +404,7 @@ impl Bar { pub fn get_x(&self) -> u8 { self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -440,15 +455,15 @@ impl BazData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 2 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Baz".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Baz", wanted: 2, got: bytes.get().remaining(), }); @@ -456,8 +471,9 @@ impl BazData { let y = bytes.get_mut().get_u16(); Ok(Self { y }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u16(self.y); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -467,23 +483,26 @@ impl BazData { } } impl Packet for Baz { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Baz> for Bytes { - fn from(packet: Baz) -> Self { - packet.to_bytes() +impl TryFrom<Baz> for Bytes { + type Error = EncodeError; + fn try_from(packet: Baz) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Baz> for Vec<u8> { - fn from(packet: Baz) -> Self { - packet.to_vec() +impl TryFrom<Baz> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Baz) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<Baz> for Foo { @@ -492,26 +511,26 @@ impl From<Baz> for Foo { } } impl TryFrom<Foo> for Baz { - type Error = Error; - fn try_from(packet: Foo) -> Result<Baz> { + type Error = DecodeError; + fn try_from(packet: Foo) -> Result<Baz, Self::Error> { Baz::new(packet.foo) } } impl Baz { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { let baz = match &foo.child { FooDataChild::Baz(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(FooDataChild::Baz), actual: format!("{:?}", & foo.child), }); @@ -528,7 +547,7 @@ impl Baz { pub fn get_y(&self) -> u16 { self.baz.y } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.baz.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_child_packets_little_endian.rs b/tests/generated/rust_legacy/packet_decl_child_packets_little_endian.rs index cebc67e..b4a96a4 100644 --- a/tests/generated/packet_decl_child_packets_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_child_packets_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Enum16 { } impl TryFrom<u16> for Enum16 { type Error = u16; - fn try_from(value: u16) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u16) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Enum16::A), 0x2 => Ok(Enum16::B), @@ -119,45 +124,45 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 4 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); } let a = bytes.get_mut().get_u8(); if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 2, got: bytes.get().remaining(), }); } let b = Enum16::try_from(bytes.get_mut().get_u16_le()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Foo".to_string(), - field: "b".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "b", value: unknown_val as u64, - type_: "Enum16".to_string(), + type_: "Enum16", })?; if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); } let payload_size = bytes.get_mut().get_u8() as usize; if bytes.get().remaining() < payload_size { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: payload_size, got: bytes.get().remaining(), }); @@ -182,22 +187,25 @@ impl FooData { }; Ok(Self { a, b, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(self.a); buffer.put_u16_le(u16::from(self.b)); if self.child.get_total_size() > 0xff { - panic!( - "Invalid length for {}::{}: {} > {}", "Foo", "_payload_", self.child - .get_total_size(), 0xff - ); + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: self.child.get_total_size(), + maximum_size: 0xff, + }); } buffer.put_u8(self.child.get_total_size() as u8); match &self.child { - FooDataChild::Bar(child) => child.write_to(buffer), - FooDataChild::Baz(child) => child.write_to(buffer), + FooDataChild::Bar(child) => child.write_to(buffer)?, + FooDataChild::Baz(child) => child.write_to(buffer)?, FooDataChild::Payload(payload) => buffer.put_slice(payload), FooDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -207,32 +215,35 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } @@ -244,7 +255,7 @@ impl Foo { FooDataChild::None => FooChild::None, } } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_a(&self) -> u8 { @@ -253,7 +264,7 @@ impl Foo { pub fn get_b(&self) -> Enum16 { self.foo.b } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -301,15 +312,15 @@ impl BarData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Bar".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Bar", wanted: 1, got: bytes.get().remaining(), }); @@ -317,8 +328,9 @@ impl BarData { let x = bytes.get_mut().get_u8(); Ok(Self { x }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(self.x); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -328,23 +340,26 @@ impl BarData { } } impl Packet for Bar { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Bar> for Bytes { - fn from(packet: Bar) -> Self { - packet.to_bytes() +impl TryFrom<Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Bar> for Vec<u8> { - fn from(packet: Bar) -> Self { - packet.to_vec() +impl TryFrom<Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<Bar> for Foo { @@ -353,26 +368,26 @@ impl From<Bar> for Foo { } } impl TryFrom<Foo> for Bar { - type Error = Error; - fn try_from(packet: Foo) -> Result<Bar> { + type Error = DecodeError; + fn try_from(packet: Foo) -> Result<Bar, Self::Error> { Bar::new(packet.foo) } } impl Bar { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { let bar = match &foo.child { FooDataChild::Bar(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(FooDataChild::Bar), actual: format!("{:?}", & foo.child), }); @@ -389,7 +404,7 @@ impl Bar { pub fn get_x(&self) -> u8 { self.bar.x } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.bar.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -440,15 +455,15 @@ impl BazData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 2 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Baz".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Baz", wanted: 2, got: bytes.get().remaining(), }); @@ -456,8 +471,9 @@ impl BazData { let y = bytes.get_mut().get_u16_le(); Ok(Self { y }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u16_le(self.y); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -467,23 +483,26 @@ impl BazData { } } impl Packet for Baz { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Baz> for Bytes { - fn from(packet: Baz) -> Self { - packet.to_bytes() +impl TryFrom<Baz> for Bytes { + type Error = EncodeError; + fn try_from(packet: Baz) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Baz> for Vec<u8> { - fn from(packet: Baz) -> Self { - packet.to_vec() +impl TryFrom<Baz> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Baz) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<Baz> for Foo { @@ -492,26 +511,26 @@ impl From<Baz> for Foo { } } impl TryFrom<Foo> for Baz { - type Error = Error; - fn try_from(packet: Foo) -> Result<Baz> { + type Error = DecodeError; + fn try_from(packet: Foo) -> Result<Baz, Self::Error> { Baz::new(packet.foo) } } impl Baz { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { let baz = match &foo.child { FooDataChild::Baz(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(FooDataChild::Baz), actual: format!("{:?}", & foo.child), }); @@ -528,7 +547,7 @@ impl Baz { pub fn get_y(&self) -> u16 { self.baz.y } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.baz.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_complex_scalars_big_endian.rs b/tests/generated/rust_legacy/packet_decl_complex_scalars_big_endian.rs index 4c3de07..af50b91 100644 --- a/tests/generated/packet_decl_complex_scalars_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_complex_scalars_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -48,15 +53,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 7 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 2, got: bytes.get().remaining(), }); @@ -66,16 +71,16 @@ impl FooData { let b = (chunk >> 3) as u8; let c = ((chunk >> 11) & 0x1f) as u8; if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); } let d = bytes.get_mut().get_uint(3) as u32; if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 2, got: bytes.get().remaining(), }); @@ -85,27 +90,53 @@ impl FooData { let f = ((chunk >> 12) & 0xf) as u8; Ok(Self { a, b, c, d, e, f }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.a > 0x7 { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "a", self.a, 0x7); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a as u64, + maximum_value: 0x7, + }); } if self.c > 0x1f { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "c", self.c, 0x1f); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "c", + value: self.c as u64, + maximum_value: 0x1f, + }); } let value = (self.a as u16) | ((self.b as u16) << 3) | ((self.c as u16) << 11); buffer.put_u16(value); if self.d > 0xff_ffff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "d", self.d, 0xff_ffff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "d", + value: self.d as u64, + maximum_value: 0xff_ffff, + }); } buffer.put_uint(self.d as u64, 3); if self.e > 0xfff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "e", self.e, 0xfff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "e", + value: self.e as u64, + maximum_value: 0xfff, + }); } if self.f > 0xf { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "f", self.f, 0xf); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "f", + value: self.f as u64, + maximum_value: 0xf, + }); } let value = self.e | ((self.f as u16) << 12); buffer.put_u16(value); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -115,36 +146,39 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_a(&self) -> u8 { @@ -165,7 +199,7 @@ impl Foo { pub fn get_f(&self) -> u8 { self.foo.f } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_complex_scalars_little_endian.rs b/tests/generated/rust_legacy/packet_decl_complex_scalars_little_endian.rs index 4bd1a80..c3b8827 100644 --- a/tests/generated/packet_decl_complex_scalars_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_complex_scalars_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -48,15 +53,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 7 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 2, got: bytes.get().remaining(), }); @@ -66,16 +71,16 @@ impl FooData { let b = (chunk >> 3) as u8; let c = ((chunk >> 11) & 0x1f) as u8; if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); } let d = bytes.get_mut().get_uint_le(3) as u32; if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 2, got: bytes.get().remaining(), }); @@ -85,27 +90,53 @@ impl FooData { let f = ((chunk >> 12) & 0xf) as u8; Ok(Self { a, b, c, d, e, f }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.a > 0x7 { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "a", self.a, 0x7); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a as u64, + maximum_value: 0x7, + }); } if self.c > 0x1f { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "c", self.c, 0x1f); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "c", + value: self.c as u64, + maximum_value: 0x1f, + }); } let value = (self.a as u16) | ((self.b as u16) << 3) | ((self.c as u16) << 11); buffer.put_u16_le(value); if self.d > 0xff_ffff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "d", self.d, 0xff_ffff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "d", + value: self.d as u64, + maximum_value: 0xff_ffff, + }); } buffer.put_uint_le(self.d as u64, 3); if self.e > 0xfff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "e", self.e, 0xfff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "e", + value: self.e as u64, + maximum_value: 0xfff, + }); } if self.f > 0xf { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "f", self.f, 0xf); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "f", + value: self.f as u64, + maximum_value: 0xf, + }); } let value = self.e | ((self.f as u16) << 12); buffer.put_u16_le(value); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -115,36 +146,39 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_a(&self) -> u8 { @@ -165,7 +199,7 @@ impl Foo { pub fn get_f(&self) -> u8 { self.foo.f } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_custom_field_big_endian.rs b/tests/generated/rust_legacy/packet_decl_custom_field_big_endian.rs index 43b2237..757c0af 100644 --- a/tests/generated/packet_decl_custom_field_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_custom_field_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(try_from = "u32", into = "u32"))] @@ -34,7 +39,7 @@ impl From<Bar1> for u32 { } impl TryFrom<u32> for Bar1 { type Error = u32; - fn try_from(value: u32) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u32) -> Result<Self, Self::Error> { if value > 0xff_ffff { Err(value) } else { Ok(Bar1(value)) } } } @@ -79,19 +84,20 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 7 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let a = (bytes.get_mut().get_uint(3) as u32).try_into().unwrap(); let b = bytes.get_mut().get_u32().into(); Ok(Self { a, b }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_uint(u32::from(self.a) as u64, 3); buffer.put_u32(u32::from(self.b)); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -101,36 +107,39 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_a(&self) -> Bar1 { @@ -139,7 +148,7 @@ impl Foo { pub fn get_b(&self) -> Bar2 { self.foo.b } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_custom_field_little_endian.rs b/tests/generated/rust_legacy/packet_decl_custom_field_little_endian.rs index f1b9d0a..e714d39 100644 --- a/tests/generated/packet_decl_custom_field_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_custom_field_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(try_from = "u32", into = "u32"))] @@ -34,7 +39,7 @@ impl From<Bar1> for u32 { } impl TryFrom<u32> for Bar1 { type Error = u32; - fn try_from(value: u32) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u32) -> Result<Self, Self::Error> { if value > 0xff_ffff { Err(value) } else { Ok(Bar1(value)) } } } @@ -79,19 +84,20 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 7 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let a = (bytes.get_mut().get_uint_le(3) as u32).try_into().unwrap(); let b = bytes.get_mut().get_u32_le().into(); Ok(Self { a, b }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_uint_le(u32::from(self.a) as u64, 3); buffer.put_u32_le(u32::from(self.b)); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -101,36 +107,39 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_a(&self) -> Bar1 { @@ -139,7 +148,7 @@ impl Foo { pub fn get_b(&self) -> Bar2 { self.foo.b } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_empty_big_endian.rs b/tests/generated/rust_legacy/packet_decl_empty_big_endian.rs index 49f14b8..e28e34c 100644 --- a/tests/generated/packet_decl_empty_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_empty_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData {} @@ -34,15 +39,17 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { Ok(Self {}) } - fn write_to(&self, buffer: &mut BytesMut) {} + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { + Ok(()) + } fn get_total_size(&self) -> usize { self.get_size() } @@ -51,39 +58,42 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_empty_little_endian.rs b/tests/generated/rust_legacy/packet_decl_empty_little_endian.rs index 49f14b8..e28e34c 100644 --- a/tests/generated/packet_decl_empty_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_empty_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData {} @@ -34,15 +39,17 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { Ok(Self {}) } - fn write_to(&self, buffer: &mut BytesMut) {} + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { + Ok(()) + } fn get_total_size(&self) -> usize { self.get_size() } @@ -51,39 +58,42 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_fixed_enum_field_big_endian.rs b/tests/generated/rust_legacy/packet_decl_fixed_enum_field_big_endian.rs index 78b2b99..e45ea28 100644 --- a/tests/generated/packet_decl_fixed_enum_field_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_fixed_enum_field_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Enum7 { } impl TryFrom<u8> for Enum7 { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Enum7::A), 0x2 => Ok(Enum7::B), @@ -104,15 +109,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 8 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 8 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 8, got: bytes.get().remaining(), }); @@ -120,7 +125,7 @@ impl FooData { let chunk = bytes.get_mut().get_u64(); let fixed_value = (chunk & 0x7f) as u8; if fixed_value != u8::from(Enum7::A) { - return Err(Error::InvalidFixedValue { + return Err(DecodeError::InvalidFixedValue { expected: u8::from(Enum7::A) as u64, actual: fixed_value as u64, }); @@ -128,15 +133,18 @@ impl FooData { let b = ((chunk >> 7) & 0x1ff_ffff_ffff_ffff_u64); Ok(Self { b }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.b > 0x1ff_ffff_ffff_ffff_u64 { - panic!( - "Invalid value for {}::{}: {} > {}", "Foo", "b", self.b, - 0x1ff_ffff_ffff_ffff_u64 - ); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "b", + value: self.b as u64, + maximum_value: 0x1ff_ffff_ffff_ffff_u64, + }); } let value = (u8::from(Enum7::A) as u64) | (self.b << 7); buffer.put_u64(value); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -146,42 +154,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_b(&self) -> u64 { self.foo.b } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_fixed_enum_field_little_endian.rs b/tests/generated/rust_legacy/packet_decl_fixed_enum_field_little_endian.rs index dfb4c25..cba5f86 100644 --- a/tests/generated/packet_decl_fixed_enum_field_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_fixed_enum_field_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Enum7 { } impl TryFrom<u8> for Enum7 { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Enum7::A), 0x2 => Ok(Enum7::B), @@ -104,15 +109,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 8 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 8 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 8, got: bytes.get().remaining(), }); @@ -120,7 +125,7 @@ impl FooData { let chunk = bytes.get_mut().get_u64_le(); let fixed_value = (chunk & 0x7f) as u8; if fixed_value != u8::from(Enum7::A) { - return Err(Error::InvalidFixedValue { + return Err(DecodeError::InvalidFixedValue { expected: u8::from(Enum7::A) as u64, actual: fixed_value as u64, }); @@ -128,15 +133,18 @@ impl FooData { let b = ((chunk >> 7) & 0x1ff_ffff_ffff_ffff_u64); Ok(Self { b }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.b > 0x1ff_ffff_ffff_ffff_u64 { - panic!( - "Invalid value for {}::{}: {} > {}", "Foo", "b", self.b, - 0x1ff_ffff_ffff_ffff_u64 - ); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "b", + value: self.b as u64, + maximum_value: 0x1ff_ffff_ffff_ffff_u64, + }); } let value = (u8::from(Enum7::A) as u64) | (self.b << 7); buffer.put_u64_le(value); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -146,42 +154,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_b(&self) -> u64 { self.foo.b } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_fixed_scalar_field_big_endian.rs b/tests/generated/rust_legacy/packet_decl_fixed_scalar_field_big_endian.rs index 2c5ad70..d4525df 100644 --- a/tests/generated/packet_decl_fixed_scalar_field_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_fixed_scalar_field_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -38,15 +43,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 8 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 8 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 8, got: bytes.get().remaining(), }); @@ -54,7 +59,7 @@ impl FooData { let chunk = bytes.get_mut().get_u64(); let fixed_value = (chunk & 0x7f) as u8; if fixed_value != 7 { - return Err(Error::InvalidFixedValue { + return Err(DecodeError::InvalidFixedValue { expected: 7, actual: fixed_value as u64, }); @@ -62,15 +67,18 @@ impl FooData { let b = ((chunk >> 7) & 0x1ff_ffff_ffff_ffff_u64); Ok(Self { b }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.b > 0x1ff_ffff_ffff_ffff_u64 { - panic!( - "Invalid value for {}::{}: {} > {}", "Foo", "b", self.b, - 0x1ff_ffff_ffff_ffff_u64 - ); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "b", + value: self.b as u64, + maximum_value: 0x1ff_ffff_ffff_ffff_u64, + }); } let value = (7 as u64) | (self.b << 7); buffer.put_u64(value); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -80,42 +88,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_b(&self) -> u64 { self.foo.b } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_fixed_scalar_field_little_endian.rs b/tests/generated/rust_legacy/packet_decl_fixed_scalar_field_little_endian.rs index b37bce0..85b3010 100644 --- a/tests/generated/packet_decl_fixed_scalar_field_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_fixed_scalar_field_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -38,15 +43,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 8 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 8 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 8, got: bytes.get().remaining(), }); @@ -54,7 +59,7 @@ impl FooData { let chunk = bytes.get_mut().get_u64_le(); let fixed_value = (chunk & 0x7f) as u8; if fixed_value != 7 { - return Err(Error::InvalidFixedValue { + return Err(DecodeError::InvalidFixedValue { expected: 7, actual: fixed_value as u64, }); @@ -62,15 +67,18 @@ impl FooData { let b = ((chunk >> 7) & 0x1ff_ffff_ffff_ffff_u64); Ok(Self { b }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.b > 0x1ff_ffff_ffff_ffff_u64 { - panic!( - "Invalid value for {}::{}: {} > {}", "Foo", "b", self.b, - 0x1ff_ffff_ffff_ffff_u64 - ); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "b", + value: self.b as u64, + maximum_value: 0x1ff_ffff_ffff_ffff_u64, + }); } let value = (7 as u64) | (self.b << 7); buffer.put_u64_le(value); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -80,42 +88,45 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_b(&self) -> u64 { self.foo.b } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_grand_children_big_endian.rs b/tests/generated/rust_legacy/packet_decl_grand_children_big_endian.rs index 64ca83f..68a8ad5 100644 --- a/tests/generated/packet_decl_grand_children_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_grand_children_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Enum16 { } impl TryFrom<u16> for Enum16 { type Error = u16; - fn try_from(value: u16) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u16) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Enum16::A), 0x2 => Ok(Enum16::B), @@ -118,65 +123,65 @@ impl ParentData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 7 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Parent".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Parent", wanted: 2, got: bytes.get().remaining(), }); } let foo = Enum16::try_from(bytes.get_mut().get_u16()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Parent".to_string(), - field: "foo".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "foo", value: unknown_val as u64, - type_: "Enum16".to_string(), + type_: "Enum16", })?; if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Parent".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Parent", wanted: 2, got: bytes.get().remaining(), }); } let bar = Enum16::try_from(bytes.get_mut().get_u16()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Parent".to_string(), - field: "bar".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "bar", value: unknown_val as u64, - type_: "Enum16".to_string(), + type_: "Enum16", })?; if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Parent".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Parent", wanted: 2, got: bytes.get().remaining(), }); } let baz = Enum16::try_from(bytes.get_mut().get_u16()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Parent".to_string(), - field: "baz".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "baz", value: unknown_val as u64, - type_: "Enum16".to_string(), + type_: "Enum16", })?; if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Parent".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Parent", wanted: 1, got: bytes.get().remaining(), }); } let payload_size = bytes.get_mut().get_u8() as usize; if bytes.get().remaining() < payload_size { - return Err(Error::InvalidLengthError { - obj: "Parent".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Parent", wanted: payload_size, got: bytes.get().remaining(), }); @@ -196,22 +201,25 @@ impl ParentData { }; Ok(Self { foo, bar, baz, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u16(u16::from(self.foo)); buffer.put_u16(u16::from(self.bar)); buffer.put_u16(u16::from(self.baz)); if self.child.get_total_size() > 0xff { - panic!( - "Invalid length for {}::{}: {} > {}", "Parent", "_payload_", self.child - .get_total_size(), 0xff - ); + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: self.child.get_total_size(), + maximum_size: 0xff, + }); } buffer.put_u8(self.child.get_total_size() as u8); match &self.child { - ParentDataChild::Child(child) => child.write_to(buffer), + ParentDataChild::Child(child) => child.write_to(buffer)?, ParentDataChild::Payload(payload) => buffer.put_slice(payload), ParentDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -221,32 +229,35 @@ impl ParentData { } } impl Packet for Parent { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) + } + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Parent> for Bytes { - fn from(packet: Parent) -> Self { - packet.to_bytes() +impl TryFrom<Parent> for Bytes { + type Error = EncodeError; + fn try_from(packet: Parent) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Parent> for Vec<u8> { - fn from(packet: Parent) -> Self { - packet.to_vec() +impl TryFrom<Parent> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Parent) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Parent { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -259,7 +270,7 @@ impl Parent { ParentDataChild::None => ParentChild::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { Ok(Self { parent }) } pub fn get_bar(&self) -> Enum16 { @@ -271,7 +282,7 @@ impl Parent { pub fn get_foo(&self) -> Enum16 { self.parent.foo } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.parent.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -346,7 +357,7 @@ impl ChildData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 2 } - fn parse(bytes: &[u8], bar: Enum16, baz: Enum16) -> Result<Self> { + fn parse(bytes: &[u8], bar: Enum16, baz: Enum16) -> Result<Self, DecodeError> { let mut cell = Cell::new(bytes); let packet = Self::parse_inner(&mut cell, bar, baz)?; Ok(packet) @@ -355,20 +366,20 @@ impl ChildData { mut bytes: &mut Cell<&[u8]>, bar: Enum16, baz: Enum16, - ) -> Result<Self> { + ) -> Result<Self, DecodeError> { if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Child".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Child", wanted: 2, got: bytes.get().remaining(), }); } let quux = Enum16::try_from(bytes.get_mut().get_u16()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Child".to_string(), - field: "quux".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Child", + field: "quux", value: unknown_val as u64, - type_: "Enum16".to_string(), + type_: "Enum16", })?; let payload = bytes.get(); bytes.get_mut().advance(payload.len()); @@ -385,13 +396,14 @@ impl ChildData { }; Ok(Self { quux, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u16(u16::from(self.quux)); match &self.child { - ChildDataChild::GrandChild(child) => child.write_to(buffer), + ChildDataChild::GrandChild(child) => child.write_to(buffer)?, ChildDataChild::Payload(payload) => buffer.put_slice(payload), ChildDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -401,23 +413,26 @@ impl ChildData { } } impl Packet for Child { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Child> for Bytes { - fn from(packet: Child) -> Self { - packet.to_bytes() +impl TryFrom<Child> for Bytes { + type Error = EncodeError; + fn try_from(packet: Child) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Child> for Vec<u8> { - fn from(packet: Child) -> Self { - packet.to_vec() +impl TryFrom<Child> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Child) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<Child> for Parent { @@ -426,18 +441,18 @@ impl From<Child> for Parent { } } impl TryFrom<Parent> for Child { - type Error = Error; - fn try_from(packet: Parent) -> Result<Child> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<Child, Self::Error> { Child::new(packet.parent) } } impl Child { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -450,11 +465,11 @@ impl Child { ChildDataChild::None => ChildChild::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let child = match &parent.child { ParentDataChild::Child(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::Child), actual: format!("{:?}", & parent.child), }); @@ -474,7 +489,7 @@ impl Child { pub fn get_quux(&self) -> Enum16 { self.child.quux } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.child.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -557,12 +572,15 @@ impl GrandChildData { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8], baz: Enum16) -> Result<Self> { + fn parse(bytes: &[u8], baz: Enum16) -> Result<Self, DecodeError> { let mut cell = Cell::new(bytes); let packet = Self::parse_inner(&mut cell, baz)?; Ok(packet) } - fn parse_inner(mut bytes: &mut Cell<&[u8]>, baz: Enum16) -> Result<Self> { + fn parse_inner( + mut bytes: &mut Cell<&[u8]>, + baz: Enum16, + ) -> Result<Self, DecodeError> { let payload = bytes.get(); bytes.get_mut().advance(payload.len()); let child = match (baz) { @@ -578,12 +596,13 @@ impl GrandChildData { }; Ok(Self { child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { match &self.child { - GrandChildDataChild::GrandGrandChild(child) => child.write_to(buffer), + GrandChildDataChild::GrandGrandChild(child) => child.write_to(buffer)?, GrandChildDataChild::Payload(payload) => buffer.put_slice(payload), GrandChildDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -593,23 +612,26 @@ impl GrandChildData { } } impl Packet for GrandChild { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) + } + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<GrandChild> for Bytes { - fn from(packet: GrandChild) -> Self { - packet.to_bytes() +impl TryFrom<GrandChild> for Bytes { + type Error = EncodeError; + fn try_from(packet: GrandChild) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<GrandChild> for Vec<u8> { - fn from(packet: GrandChild) -> Self { - packet.to_vec() +impl TryFrom<GrandChild> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: GrandChild) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<GrandChild> for Parent { @@ -623,18 +645,18 @@ impl From<GrandChild> for Child { } } impl TryFrom<Parent> for GrandChild { - type Error = Error; - fn try_from(packet: Parent) -> Result<GrandChild> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<GrandChild, Self::Error> { GrandChild::new(packet.parent) } } impl GrandChild { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -651,11 +673,11 @@ impl GrandChild { GrandChildDataChild::None => GrandChildChild::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let child = match &parent.child { ParentDataChild::Child(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::Child), actual: format!("{:?}", & parent.child), }); @@ -664,7 +686,7 @@ impl GrandChild { let grandchild = match &child.child { ChildDataChild::GrandChild(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ChildDataChild::GrandChild), actual: format!("{:?}", & child.child), }); @@ -684,7 +706,7 @@ impl GrandChild { pub fn get_quux(&self) -> Enum16 { self.child.quux } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.grandchild.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -773,12 +795,12 @@ impl GrandGrandChildData { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let payload = bytes.get(); bytes.get_mut().advance(payload.len()); let child = match () { @@ -789,11 +811,12 @@ impl GrandGrandChildData { }; Ok(Self { child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { match &self.child { GrandGrandChildDataChild::Payload(payload) => buffer.put_slice(payload), GrandGrandChildDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -803,23 +826,26 @@ impl GrandGrandChildData { } } impl Packet for GrandGrandChild { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<GrandGrandChild> for Bytes { - fn from(packet: GrandGrandChild) -> Self { - packet.to_bytes() +impl TryFrom<GrandGrandChild> for Bytes { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<GrandGrandChild> for Vec<u8> { - fn from(packet: GrandGrandChild) -> Self { - packet.to_vec() +impl TryFrom<GrandGrandChild> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<GrandGrandChild> for Parent { @@ -838,18 +864,18 @@ impl From<GrandGrandChild> for GrandChild { } } impl TryFrom<Parent> for GrandGrandChild { - type Error = Error; - fn try_from(packet: Parent) -> Result<GrandGrandChild> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<GrandGrandChild, Self::Error> { GrandGrandChild::new(packet.parent) } } impl GrandGrandChild { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -861,11 +887,11 @@ impl GrandGrandChild { GrandGrandChildDataChild::None => GrandGrandChildChild::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let child = match &parent.child { ParentDataChild::Child(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::Child), actual: format!("{:?}", & parent.child), }); @@ -874,7 +900,7 @@ impl GrandGrandChild { let grandchild = match &child.child { ChildDataChild::GrandChild(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ChildDataChild::GrandChild), actual: format!("{:?}", & child.child), }); @@ -883,7 +909,7 @@ impl GrandGrandChild { let grandgrandchild = match &grandchild.child { GrandChildDataChild::GrandGrandChild(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(GrandChildDataChild::GrandGrandChild), actual: format!("{:?}", & grandchild.child), }); @@ -914,7 +940,7 @@ impl GrandGrandChild { GrandGrandChildDataChild::None => &[], } } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.grandgrandchild.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_grand_children_little_endian.rs b/tests/generated/rust_legacy/packet_decl_grand_children_little_endian.rs index 9c03220..baa83db 100644 --- a/tests/generated/packet_decl_grand_children_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_grand_children_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Enum16 { } impl TryFrom<u16> for Enum16 { type Error = u16; - fn try_from(value: u16) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u16) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Enum16::A), 0x2 => Ok(Enum16::B), @@ -118,65 +123,65 @@ impl ParentData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 7 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Parent".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Parent", wanted: 2, got: bytes.get().remaining(), }); } let foo = Enum16::try_from(bytes.get_mut().get_u16_le()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Parent".to_string(), - field: "foo".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "foo", value: unknown_val as u64, - type_: "Enum16".to_string(), + type_: "Enum16", })?; if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Parent".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Parent", wanted: 2, got: bytes.get().remaining(), }); } let bar = Enum16::try_from(bytes.get_mut().get_u16_le()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Parent".to_string(), - field: "bar".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "bar", value: unknown_val as u64, - type_: "Enum16".to_string(), + type_: "Enum16", })?; if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Parent".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Parent", wanted: 2, got: bytes.get().remaining(), }); } let baz = Enum16::try_from(bytes.get_mut().get_u16_le()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Parent".to_string(), - field: "baz".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "baz", value: unknown_val as u64, - type_: "Enum16".to_string(), + type_: "Enum16", })?; if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Parent".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Parent", wanted: 1, got: bytes.get().remaining(), }); } let payload_size = bytes.get_mut().get_u8() as usize; if bytes.get().remaining() < payload_size { - return Err(Error::InvalidLengthError { - obj: "Parent".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Parent", wanted: payload_size, got: bytes.get().remaining(), }); @@ -196,22 +201,25 @@ impl ParentData { }; Ok(Self { foo, bar, baz, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u16_le(u16::from(self.foo)); buffer.put_u16_le(u16::from(self.bar)); buffer.put_u16_le(u16::from(self.baz)); if self.child.get_total_size() > 0xff { - panic!( - "Invalid length for {}::{}: {} > {}", "Parent", "_payload_", self.child - .get_total_size(), 0xff - ); + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: self.child.get_total_size(), + maximum_size: 0xff, + }); } buffer.put_u8(self.child.get_total_size() as u8); match &self.child { - ParentDataChild::Child(child) => child.write_to(buffer), + ParentDataChild::Child(child) => child.write_to(buffer)?, ParentDataChild::Payload(payload) => buffer.put_slice(payload), ParentDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -221,32 +229,35 @@ impl ParentData { } } impl Packet for Parent { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) + } + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Parent> for Bytes { - fn from(packet: Parent) -> Self { - packet.to_bytes() +impl TryFrom<Parent> for Bytes { + type Error = EncodeError; + fn try_from(packet: Parent) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Parent> for Vec<u8> { - fn from(packet: Parent) -> Self { - packet.to_vec() +impl TryFrom<Parent> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Parent) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Parent { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -259,7 +270,7 @@ impl Parent { ParentDataChild::None => ParentChild::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { Ok(Self { parent }) } pub fn get_bar(&self) -> Enum16 { @@ -271,7 +282,7 @@ impl Parent { pub fn get_foo(&self) -> Enum16 { self.parent.foo } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.parent.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -346,7 +357,7 @@ impl ChildData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 2 } - fn parse(bytes: &[u8], bar: Enum16, baz: Enum16) -> Result<Self> { + fn parse(bytes: &[u8], bar: Enum16, baz: Enum16) -> Result<Self, DecodeError> { let mut cell = Cell::new(bytes); let packet = Self::parse_inner(&mut cell, bar, baz)?; Ok(packet) @@ -355,20 +366,20 @@ impl ChildData { mut bytes: &mut Cell<&[u8]>, bar: Enum16, baz: Enum16, - ) -> Result<Self> { + ) -> Result<Self, DecodeError> { if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Child".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Child", wanted: 2, got: bytes.get().remaining(), }); } let quux = Enum16::try_from(bytes.get_mut().get_u16_le()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Child".to_string(), - field: "quux".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Child", + field: "quux", value: unknown_val as u64, - type_: "Enum16".to_string(), + type_: "Enum16", })?; let payload = bytes.get(); bytes.get_mut().advance(payload.len()); @@ -385,13 +396,14 @@ impl ChildData { }; Ok(Self { quux, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u16_le(u16::from(self.quux)); match &self.child { - ChildDataChild::GrandChild(child) => child.write_to(buffer), + ChildDataChild::GrandChild(child) => child.write_to(buffer)?, ChildDataChild::Payload(payload) => buffer.put_slice(payload), ChildDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -401,23 +413,26 @@ impl ChildData { } } impl Packet for Child { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Child> for Bytes { - fn from(packet: Child) -> Self { - packet.to_bytes() +impl TryFrom<Child> for Bytes { + type Error = EncodeError; + fn try_from(packet: Child) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Child> for Vec<u8> { - fn from(packet: Child) -> Self { - packet.to_vec() +impl TryFrom<Child> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Child) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<Child> for Parent { @@ -426,18 +441,18 @@ impl From<Child> for Parent { } } impl TryFrom<Parent> for Child { - type Error = Error; - fn try_from(packet: Parent) -> Result<Child> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<Child, Self::Error> { Child::new(packet.parent) } } impl Child { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -450,11 +465,11 @@ impl Child { ChildDataChild::None => ChildChild::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let child = match &parent.child { ParentDataChild::Child(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::Child), actual: format!("{:?}", & parent.child), }); @@ -474,7 +489,7 @@ impl Child { pub fn get_quux(&self) -> Enum16 { self.child.quux } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.child.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -557,12 +572,15 @@ impl GrandChildData { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8], baz: Enum16) -> Result<Self> { + fn parse(bytes: &[u8], baz: Enum16) -> Result<Self, DecodeError> { let mut cell = Cell::new(bytes); let packet = Self::parse_inner(&mut cell, baz)?; Ok(packet) } - fn parse_inner(mut bytes: &mut Cell<&[u8]>, baz: Enum16) -> Result<Self> { + fn parse_inner( + mut bytes: &mut Cell<&[u8]>, + baz: Enum16, + ) -> Result<Self, DecodeError> { let payload = bytes.get(); bytes.get_mut().advance(payload.len()); let child = match (baz) { @@ -578,12 +596,13 @@ impl GrandChildData { }; Ok(Self { child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { match &self.child { - GrandChildDataChild::GrandGrandChild(child) => child.write_to(buffer), + GrandChildDataChild::GrandGrandChild(child) => child.write_to(buffer)?, GrandChildDataChild::Payload(payload) => buffer.put_slice(payload), GrandChildDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -593,23 +612,26 @@ impl GrandChildData { } } impl Packet for GrandChild { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) + } + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<GrandChild> for Bytes { - fn from(packet: GrandChild) -> Self { - packet.to_bytes() +impl TryFrom<GrandChild> for Bytes { + type Error = EncodeError; + fn try_from(packet: GrandChild) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<GrandChild> for Vec<u8> { - fn from(packet: GrandChild) -> Self { - packet.to_vec() +impl TryFrom<GrandChild> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: GrandChild) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<GrandChild> for Parent { @@ -623,18 +645,18 @@ impl From<GrandChild> for Child { } } impl TryFrom<Parent> for GrandChild { - type Error = Error; - fn try_from(packet: Parent) -> Result<GrandChild> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<GrandChild, Self::Error> { GrandChild::new(packet.parent) } } impl GrandChild { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -651,11 +673,11 @@ impl GrandChild { GrandChildDataChild::None => GrandChildChild::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let child = match &parent.child { ParentDataChild::Child(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::Child), actual: format!("{:?}", & parent.child), }); @@ -664,7 +686,7 @@ impl GrandChild { let grandchild = match &child.child { ChildDataChild::GrandChild(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ChildDataChild::GrandChild), actual: format!("{:?}", & child.child), }); @@ -684,7 +706,7 @@ impl GrandChild { pub fn get_quux(&self) -> Enum16 { self.child.quux } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.grandchild.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -773,12 +795,12 @@ impl GrandGrandChildData { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let payload = bytes.get(); bytes.get_mut().advance(payload.len()); let child = match () { @@ -789,11 +811,12 @@ impl GrandGrandChildData { }; Ok(Self { child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { match &self.child { GrandGrandChildDataChild::Payload(payload) => buffer.put_slice(payload), GrandGrandChildDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -803,23 +826,26 @@ impl GrandGrandChildData { } } impl Packet for GrandGrandChild { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<GrandGrandChild> for Bytes { - fn from(packet: GrandGrandChild) -> Self { - packet.to_bytes() +impl TryFrom<GrandGrandChild> for Bytes { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<GrandGrandChild> for Vec<u8> { - fn from(packet: GrandGrandChild) -> Self { - packet.to_vec() +impl TryFrom<GrandGrandChild> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: GrandGrandChild) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<GrandGrandChild> for Parent { @@ -838,18 +864,18 @@ impl From<GrandGrandChild> for GrandChild { } } impl TryFrom<Parent> for GrandGrandChild { - type Error = Error; - fn try_from(packet: Parent) -> Result<GrandGrandChild> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<GrandGrandChild, Self::Error> { GrandGrandChild::new(packet.parent) } } impl GrandGrandChild { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -861,11 +887,11 @@ impl GrandGrandChild { GrandGrandChildDataChild::None => GrandGrandChildChild::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let child = match &parent.child { ParentDataChild::Child(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::Child), actual: format!("{:?}", & parent.child), }); @@ -874,7 +900,7 @@ impl GrandGrandChild { let grandchild = match &child.child { ChildDataChild::GrandChild(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ChildDataChild::GrandChild), actual: format!("{:?}", & child.child), }); @@ -883,7 +909,7 @@ impl GrandGrandChild { let grandgrandchild = match &grandchild.child { GrandChildDataChild::GrandGrandChild(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(GrandChildDataChild::GrandGrandChild), actual: format!("{:?}", & grandchild.child), }); @@ -914,7 +940,7 @@ impl GrandGrandChild { GrandGrandChildDataChild::None => &[], } } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.grandgrandchild.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_mask_scalar_value_big_endian.rs b/tests/generated/rust_legacy/packet_decl_mask_scalar_value_big_endian.rs index dddbc0b..fc554df 100644 --- a/tests/generated/packet_decl_mask_scalar_value_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_mask_scalar_value_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -42,15 +47,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 4 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 4 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 4, got: bytes.get().remaining(), }); @@ -61,18 +66,34 @@ impl FooData { let c = ((chunk >> 26) & 0x3f) as u8; Ok(Self { a, b, c }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.a > 0x3 { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "a", self.a, 0x3); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a as u64, + maximum_value: 0x3, + }); } if self.b > 0xff_ffff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "b", self.b, 0xff_ffff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "b", + value: self.b as u64, + maximum_value: 0xff_ffff, + }); } if self.c > 0x3f { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "c", self.c, 0x3f); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "c", + value: self.c as u64, + maximum_value: 0x3f, + }); } let value = (self.a as u32) | (self.b << 2) | ((self.c as u32) << 26); buffer.put_u32(value); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -82,36 +103,39 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_a(&self) -> u8 { @@ -123,7 +147,7 @@ impl Foo { pub fn get_c(&self) -> u8 { self.foo.c } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_mask_scalar_value_little_endian.rs b/tests/generated/rust_legacy/packet_decl_mask_scalar_value_little_endian.rs index 57bcb51..a736eb7 100644 --- a/tests/generated/packet_decl_mask_scalar_value_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_mask_scalar_value_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -42,15 +47,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 4 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 4 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 4, got: bytes.get().remaining(), }); @@ -61,18 +66,34 @@ impl FooData { let c = ((chunk >> 26) & 0x3f) as u8; Ok(Self { a, b, c }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.a > 0x3 { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "a", self.a, 0x3); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a as u64, + maximum_value: 0x3, + }); } if self.b > 0xff_ffff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "b", self.b, 0xff_ffff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "b", + value: self.b as u64, + maximum_value: 0xff_ffff, + }); } if self.c > 0x3f { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "c", self.c, 0x3f); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "c", + value: self.c as u64, + maximum_value: 0x3f, + }); } let value = (self.a as u32) | (self.b << 2) | ((self.c as u32) << 26); buffer.put_u32_le(value); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -82,36 +103,39 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_a(&self) -> u8 { @@ -123,7 +147,7 @@ impl Foo { pub fn get_c(&self) -> u8 { self.foo.c } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_mixed_scalars_enums_big_endian.rs b/tests/generated/rust_legacy/packet_decl_mixed_scalars_enums_big_endian.rs index 1bf676b..16f516b 100644 --- a/tests/generated/packet_decl_mixed_scalars_enums_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_mixed_scalars_enums_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Enum7 { } impl TryFrom<u8> for Enum7 { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Enum7::A), 0x2 => Ok(Enum7::B), @@ -94,7 +99,7 @@ pub enum Enum9 { } impl TryFrom<u16> for Enum9 { type Error = u16; - fn try_from(value: u16) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u16) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Enum9::A), 0x2 => Ok(Enum9::B), @@ -166,48 +171,59 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 3 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); } 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 { - obj: "Foo".to_string(), - field: "x".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "x", value: unknown_val as u64, - type_: "Enum7".to_string(), + type_: "Enum7", })?; let y = ((chunk >> 7) & 0x1f) as u8; let z = Enum9::try_from(((chunk >> 12) & 0x1ff) as u16) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Foo".to_string(), - field: "z".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "z", value: unknown_val as u64, - type_: "Enum9".to_string(), + type_: "Enum9", })?; let w = ((chunk >> 21) & 0x7) as u8; Ok(Self { x, y, z, w }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.y > 0x1f { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "y", self.y, 0x1f); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "y", + value: self.y as u64, + maximum_value: 0x1f, + }); } if self.w > 0x7 { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "w", self.w, 0x7); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "w", + value: self.w as u64, + maximum_value: 0x7, + }); } let value = (u8::from(self.x) as u32) | ((self.y as u32) << 7) | ((u16::from(self.z) as u32) << 12) | ((self.w as u32) << 21); buffer.put_uint(value as u64, 3); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -217,36 +233,39 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_w(&self) -> u8 { @@ -261,7 +280,7 @@ impl Foo { pub fn get_z(&self) -> Enum9 { self.foo.z } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_mixed_scalars_enums_little_endian.rs b/tests/generated/rust_legacy/packet_decl_mixed_scalars_enums_little_endian.rs index baa27e3..74f1b15 100644 --- a/tests/generated/packet_decl_mixed_scalars_enums_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_mixed_scalars_enums_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -28,7 +33,7 @@ pub enum Enum7 { } impl TryFrom<u8> for Enum7 { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Enum7::A), 0x2 => Ok(Enum7::B), @@ -94,7 +99,7 @@ pub enum Enum9 { } impl TryFrom<u16> for Enum9 { type Error = u16; - fn try_from(value: u16) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u16) -> Result<Self, Self::Error> { match value { 0x1 => Ok(Enum9::A), 0x2 => Ok(Enum9::B), @@ -166,48 +171,59 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 3 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); } 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 { - obj: "Foo".to_string(), - field: "x".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "x", value: unknown_val as u64, - type_: "Enum7".to_string(), + type_: "Enum7", })?; let y = ((chunk >> 7) & 0x1f) as u8; let z = Enum9::try_from(((chunk >> 12) & 0x1ff) as u16) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Foo".to_string(), - field: "z".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "z", value: unknown_val as u64, - type_: "Enum9".to_string(), + type_: "Enum9", })?; let w = ((chunk >> 21) & 0x7) as u8; Ok(Self { x, y, z, w }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.y > 0x1f { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "y", self.y, 0x1f); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "y", + value: self.y as u64, + maximum_value: 0x1f, + }); } if self.w > 0x7 { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "w", self.w, 0x7); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "w", + value: self.w as u64, + maximum_value: 0x7, + }); } let value = (u8::from(self.x) as u32) | ((self.y as u32) << 7) | ((u16::from(self.z) as u32) << 12) | ((self.w as u32) << 21); buffer.put_uint_le(value as u64, 3); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -217,36 +233,39 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_w(&self) -> u8 { @@ -261,7 +280,7 @@ impl Foo { pub fn get_z(&self) -> Enum9 { self.foo.z } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_parent_with_alias_child_big_endian.rs b/tests/generated/rust_legacy/packet_decl_parent_with_alias_child_big_endian.rs index c0a1cf1..7622688 100644 --- a/tests/generated/packet_decl_parent_with_alias_child_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_parent_with_alias_child_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -29,7 +34,7 @@ pub enum Enum8 { } impl TryFrom<u8> for Enum8 { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(Enum8::A), 0x1 => Ok(Enum8::B), @@ -130,25 +135,25 @@ impl ParentData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Parent".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Parent", wanted: 1, got: bytes.get().remaining(), }); } let v = Enum8::try_from(bytes.get_mut().get_u8()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Parent".to_string(), - field: "v".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "v", value: unknown_val as u64, - type_: "Enum8".to_string(), + type_: "Enum8", })?; let payload = bytes.get(); bytes.get_mut().advance(payload.len()); @@ -170,14 +175,15 @@ impl ParentData { }; Ok(Self { v, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(u8::from(self.v)); match &self.child { - ParentDataChild::AliasChild(child) => child.write_to(buffer), - ParentDataChild::NormalChild(child) => child.write_to(buffer), + ParentDataChild::AliasChild(child) => child.write_to(buffer)?, + ParentDataChild::NormalChild(child) => child.write_to(buffer)?, ParentDataChild::Payload(payload) => buffer.put_slice(payload), ParentDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -187,32 +193,35 @@ impl ParentData { } } impl Packet for Parent { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Parent> for Bytes { - fn from(packet: Parent) -> Self { - packet.to_bytes() +impl TryFrom<Parent> for Bytes { + type Error = EncodeError; + fn try_from(packet: Parent) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Parent> for Vec<u8> { - fn from(packet: Parent) -> Self { - packet.to_vec() +impl TryFrom<Parent> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Parent) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Parent { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -228,13 +237,13 @@ impl Parent { ParentDataChild::None => ParentChild::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { Ok(Self { parent }) } pub fn get_v(&self) -> Enum8 { self.parent.v } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.parent.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -307,12 +316,12 @@ impl AliasChildData { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8], v: Enum8) -> Result<Self> { + fn parse(bytes: &[u8], v: Enum8) -> Result<Self, DecodeError> { let mut cell = Cell::new(bytes); let packet = Self::parse_inner(&mut cell, v)?; Ok(packet) } - fn parse_inner(mut bytes: &mut Cell<&[u8]>, v: Enum8) -> Result<Self> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>, v: Enum8) -> Result<Self, DecodeError> { let payload = bytes.get(); bytes.get_mut().advance(payload.len()); let child = match (v) { @@ -333,13 +342,14 @@ impl AliasChildData { }; Ok(Self { child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { match &self.child { - AliasChildDataChild::NormalGrandChild1(child) => child.write_to(buffer), - AliasChildDataChild::NormalGrandChild2(child) => child.write_to(buffer), + AliasChildDataChild::NormalGrandChild1(child) => child.write_to(buffer)?, + AliasChildDataChild::NormalGrandChild2(child) => child.write_to(buffer)?, AliasChildDataChild::Payload(payload) => buffer.put_slice(payload), AliasChildDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -349,23 +359,26 @@ impl AliasChildData { } } impl Packet for AliasChild { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<AliasChild> for Bytes { - fn from(packet: AliasChild) -> Self { - packet.to_bytes() +impl TryFrom<AliasChild> for Bytes { + type Error = EncodeError; + fn try_from(packet: AliasChild) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<AliasChild> for Vec<u8> { - fn from(packet: AliasChild) -> Self { - packet.to_vec() +impl TryFrom<AliasChild> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: AliasChild) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<AliasChild> for Parent { @@ -374,18 +387,18 @@ impl From<AliasChild> for Parent { } } impl TryFrom<Parent> for AliasChild { - type Error = Error; - fn try_from(packet: Parent) -> Result<AliasChild> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<AliasChild, Self::Error> { AliasChild::new(packet.parent) } } impl AliasChild { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -407,11 +420,11 @@ impl AliasChild { AliasChildDataChild::None => AliasChildChild::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let aliaschild = match &parent.child { ParentDataChild::AliasChild(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::AliasChild), actual: format!("{:?}", & parent.child), }); @@ -422,7 +435,7 @@ impl AliasChild { pub fn get_v(&self) -> Enum8 { self.parent.v } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.aliaschild.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -472,15 +485,17 @@ impl NormalChildData { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { Ok(Self {}) } - fn write_to(&self, buffer: &mut BytesMut) {} + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { + Ok(()) + } fn get_total_size(&self) -> usize { self.get_size() } @@ -489,23 +504,26 @@ impl NormalChildData { } } impl Packet for NormalChild { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<NormalChild> for Bytes { - fn from(packet: NormalChild) -> Self { - packet.to_bytes() +impl TryFrom<NormalChild> for Bytes { + type Error = EncodeError; + fn try_from(packet: NormalChild) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<NormalChild> for Vec<u8> { - fn from(packet: NormalChild) -> Self { - packet.to_vec() +impl TryFrom<NormalChild> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: NormalChild) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<NormalChild> for Parent { @@ -514,26 +532,26 @@ impl From<NormalChild> for Parent { } } impl TryFrom<Parent> for NormalChild { - type Error = Error; - fn try_from(packet: Parent) -> Result<NormalChild> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<NormalChild, Self::Error> { NormalChild::new(packet.parent) } } impl NormalChild { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let normalchild = match &parent.child { ParentDataChild::NormalChild(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::NormalChild), actual: format!("{:?}", & parent.child), }); @@ -544,7 +562,7 @@ impl NormalChild { pub fn get_v(&self) -> Enum8 { self.parent.v } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.normalchild.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -591,15 +609,17 @@ impl NormalGrandChild1Data { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { Ok(Self {}) } - fn write_to(&self, buffer: &mut BytesMut) {} + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { + Ok(()) + } fn get_total_size(&self) -> usize { self.get_size() } @@ -608,23 +628,26 @@ impl NormalGrandChild1Data { } } impl Packet for NormalGrandChild1 { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) + } + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<NormalGrandChild1> for Bytes { - fn from(packet: NormalGrandChild1) -> Self { - packet.to_bytes() +impl TryFrom<NormalGrandChild1> for Bytes { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild1) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<NormalGrandChild1> for Vec<u8> { - fn from(packet: NormalGrandChild1) -> Self { - packet.to_vec() +impl TryFrom<NormalGrandChild1> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild1) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<NormalGrandChild1> for Parent { @@ -638,26 +661,26 @@ impl From<NormalGrandChild1> for AliasChild { } } impl TryFrom<Parent> for NormalGrandChild1 { - type Error = Error; - fn try_from(packet: Parent) -> Result<NormalGrandChild1> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<NormalGrandChild1, Self::Error> { NormalGrandChild1::new(packet.parent) } } impl NormalGrandChild1 { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let aliaschild = match &parent.child { ParentDataChild::AliasChild(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::AliasChild), actual: format!("{:?}", & parent.child), }); @@ -666,7 +689,7 @@ impl NormalGrandChild1 { let normalgrandchild1 = match &aliaschild.child { AliasChildDataChild::NormalGrandChild1(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(AliasChildDataChild::NormalGrandChild1), actual: format!("{:?}", & aliaschild.child), }); @@ -681,7 +704,7 @@ impl NormalGrandChild1 { pub fn get_v(&self) -> Enum8 { self.parent.v } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.normalgrandchild1.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -760,12 +783,12 @@ impl NormalGrandChild2Data { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let payload = bytes.get(); bytes.get_mut().advance(payload.len()); let child = match () { @@ -776,11 +799,12 @@ impl NormalGrandChild2Data { }; Ok(Self { child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { match &self.child { NormalGrandChild2DataChild::Payload(payload) => buffer.put_slice(payload), NormalGrandChild2DataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -790,23 +814,26 @@ impl NormalGrandChild2Data { } } impl Packet for NormalGrandChild2 { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<NormalGrandChild2> for Bytes { - fn from(packet: NormalGrandChild2) -> Self { - packet.to_bytes() +impl TryFrom<NormalGrandChild2> for Bytes { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild2) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<NormalGrandChild2> for Vec<u8> { - fn from(packet: NormalGrandChild2) -> Self { - packet.to_vec() +impl TryFrom<NormalGrandChild2> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild2) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<NormalGrandChild2> for Parent { @@ -820,18 +847,18 @@ impl From<NormalGrandChild2> for AliasChild { } } impl TryFrom<Parent> for NormalGrandChild2 { - type Error = Error; - fn try_from(packet: Parent) -> Result<NormalGrandChild2> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<NormalGrandChild2, Self::Error> { NormalGrandChild2::new(packet.parent) } } impl NormalGrandChild2 { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -843,11 +870,11 @@ impl NormalGrandChild2 { NormalGrandChild2DataChild::None => NormalGrandChild2Child::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let aliaschild = match &parent.child { ParentDataChild::AliasChild(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::AliasChild), actual: format!("{:?}", & parent.child), }); @@ -856,7 +883,7 @@ impl NormalGrandChild2 { let normalgrandchild2 = match &aliaschild.child { AliasChildDataChild::NormalGrandChild2(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(AliasChildDataChild::NormalGrandChild2), actual: format!("{:?}", & aliaschild.child), }); @@ -877,7 +904,7 @@ impl NormalGrandChild2 { NormalGrandChild2DataChild::None => &[], } } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.normalgrandchild2.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_parent_with_alias_child_little_endian.rs b/tests/generated/rust_legacy/packet_decl_parent_with_alias_child_little_endian.rs index c0a1cf1..7622688 100644 --- a/tests/generated/packet_decl_parent_with_alias_child_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_parent_with_alias_child_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -29,7 +34,7 @@ pub enum Enum8 { } impl TryFrom<u8> for Enum8 { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(Enum8::A), 0x1 => Ok(Enum8::B), @@ -130,25 +135,25 @@ impl ParentData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Parent".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Parent", wanted: 1, got: bytes.get().remaining(), }); } let v = Enum8::try_from(bytes.get_mut().get_u8()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Parent".to_string(), - field: "v".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "v", value: unknown_val as u64, - type_: "Enum8".to_string(), + type_: "Enum8", })?; let payload = bytes.get(); bytes.get_mut().advance(payload.len()); @@ -170,14 +175,15 @@ impl ParentData { }; Ok(Self { v, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(u8::from(self.v)); match &self.child { - ParentDataChild::AliasChild(child) => child.write_to(buffer), - ParentDataChild::NormalChild(child) => child.write_to(buffer), + ParentDataChild::AliasChild(child) => child.write_to(buffer)?, + ParentDataChild::NormalChild(child) => child.write_to(buffer)?, ParentDataChild::Payload(payload) => buffer.put_slice(payload), ParentDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -187,32 +193,35 @@ impl ParentData { } } impl Packet for Parent { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Parent> for Bytes { - fn from(packet: Parent) -> Self { - packet.to_bytes() +impl TryFrom<Parent> for Bytes { + type Error = EncodeError; + fn try_from(packet: Parent) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Parent> for Vec<u8> { - fn from(packet: Parent) -> Self { - packet.to_vec() +impl TryFrom<Parent> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Parent) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Parent { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -228,13 +237,13 @@ impl Parent { ParentDataChild::None => ParentChild::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { Ok(Self { parent }) } pub fn get_v(&self) -> Enum8 { self.parent.v } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.parent.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -307,12 +316,12 @@ impl AliasChildData { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8], v: Enum8) -> Result<Self> { + fn parse(bytes: &[u8], v: Enum8) -> Result<Self, DecodeError> { let mut cell = Cell::new(bytes); let packet = Self::parse_inner(&mut cell, v)?; Ok(packet) } - fn parse_inner(mut bytes: &mut Cell<&[u8]>, v: Enum8) -> Result<Self> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>, v: Enum8) -> Result<Self, DecodeError> { let payload = bytes.get(); bytes.get_mut().advance(payload.len()); let child = match (v) { @@ -333,13 +342,14 @@ impl AliasChildData { }; Ok(Self { child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { match &self.child { - AliasChildDataChild::NormalGrandChild1(child) => child.write_to(buffer), - AliasChildDataChild::NormalGrandChild2(child) => child.write_to(buffer), + AliasChildDataChild::NormalGrandChild1(child) => child.write_to(buffer)?, + AliasChildDataChild::NormalGrandChild2(child) => child.write_to(buffer)?, AliasChildDataChild::Payload(payload) => buffer.put_slice(payload), AliasChildDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -349,23 +359,26 @@ impl AliasChildData { } } impl Packet for AliasChild { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<AliasChild> for Bytes { - fn from(packet: AliasChild) -> Self { - packet.to_bytes() +impl TryFrom<AliasChild> for Bytes { + type Error = EncodeError; + fn try_from(packet: AliasChild) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<AliasChild> for Vec<u8> { - fn from(packet: AliasChild) -> Self { - packet.to_vec() +impl TryFrom<AliasChild> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: AliasChild) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<AliasChild> for Parent { @@ -374,18 +387,18 @@ impl From<AliasChild> for Parent { } } impl TryFrom<Parent> for AliasChild { - type Error = Error; - fn try_from(packet: Parent) -> Result<AliasChild> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<AliasChild, Self::Error> { AliasChild::new(packet.parent) } } impl AliasChild { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -407,11 +420,11 @@ impl AliasChild { AliasChildDataChild::None => AliasChildChild::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let aliaschild = match &parent.child { ParentDataChild::AliasChild(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::AliasChild), actual: format!("{:?}", & parent.child), }); @@ -422,7 +435,7 @@ impl AliasChild { pub fn get_v(&self) -> Enum8 { self.parent.v } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.aliaschild.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -472,15 +485,17 @@ impl NormalChildData { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { Ok(Self {}) } - fn write_to(&self, buffer: &mut BytesMut) {} + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { + Ok(()) + } fn get_total_size(&self) -> usize { self.get_size() } @@ -489,23 +504,26 @@ impl NormalChildData { } } impl Packet for NormalChild { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<NormalChild> for Bytes { - fn from(packet: NormalChild) -> Self { - packet.to_bytes() +impl TryFrom<NormalChild> for Bytes { + type Error = EncodeError; + fn try_from(packet: NormalChild) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<NormalChild> for Vec<u8> { - fn from(packet: NormalChild) -> Self { - packet.to_vec() +impl TryFrom<NormalChild> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: NormalChild) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<NormalChild> for Parent { @@ -514,26 +532,26 @@ impl From<NormalChild> for Parent { } } impl TryFrom<Parent> for NormalChild { - type Error = Error; - fn try_from(packet: Parent) -> Result<NormalChild> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<NormalChild, Self::Error> { NormalChild::new(packet.parent) } } impl NormalChild { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let normalchild = match &parent.child { ParentDataChild::NormalChild(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::NormalChild), actual: format!("{:?}", & parent.child), }); @@ -544,7 +562,7 @@ impl NormalChild { pub fn get_v(&self) -> Enum8 { self.parent.v } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.normalchild.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -591,15 +609,17 @@ impl NormalGrandChild1Data { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { Ok(Self {}) } - fn write_to(&self, buffer: &mut BytesMut) {} + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { + Ok(()) + } fn get_total_size(&self) -> usize { self.get_size() } @@ -608,23 +628,26 @@ impl NormalGrandChild1Data { } } impl Packet for NormalGrandChild1 { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) + } + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<NormalGrandChild1> for Bytes { - fn from(packet: NormalGrandChild1) -> Self { - packet.to_bytes() +impl TryFrom<NormalGrandChild1> for Bytes { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild1) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<NormalGrandChild1> for Vec<u8> { - fn from(packet: NormalGrandChild1) -> Self { - packet.to_vec() +impl TryFrom<NormalGrandChild1> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild1) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<NormalGrandChild1> for Parent { @@ -638,26 +661,26 @@ impl From<NormalGrandChild1> for AliasChild { } } impl TryFrom<Parent> for NormalGrandChild1 { - type Error = Error; - fn try_from(packet: Parent) -> Result<NormalGrandChild1> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<NormalGrandChild1, Self::Error> { NormalGrandChild1::new(packet.parent) } } impl NormalGrandChild1 { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let aliaschild = match &parent.child { ParentDataChild::AliasChild(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::AliasChild), actual: format!("{:?}", & parent.child), }); @@ -666,7 +689,7 @@ impl NormalGrandChild1 { let normalgrandchild1 = match &aliaschild.child { AliasChildDataChild::NormalGrandChild1(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(AliasChildDataChild::NormalGrandChild1), actual: format!("{:?}", & aliaschild.child), }); @@ -681,7 +704,7 @@ impl NormalGrandChild1 { pub fn get_v(&self) -> Enum8 { self.parent.v } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.normalgrandchild1.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -760,12 +783,12 @@ impl NormalGrandChild2Data { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let payload = bytes.get(); bytes.get_mut().advance(payload.len()); let child = match () { @@ -776,11 +799,12 @@ impl NormalGrandChild2Data { }; Ok(Self { child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { match &self.child { NormalGrandChild2DataChild::Payload(payload) => buffer.put_slice(payload), NormalGrandChild2DataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -790,23 +814,26 @@ impl NormalGrandChild2Data { } } impl Packet for NormalGrandChild2 { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<NormalGrandChild2> for Bytes { - fn from(packet: NormalGrandChild2) -> Self { - packet.to_bytes() +impl TryFrom<NormalGrandChild2> for Bytes { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild2) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<NormalGrandChild2> for Vec<u8> { - fn from(packet: NormalGrandChild2) -> Self { - packet.to_vec() +impl TryFrom<NormalGrandChild2> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: NormalGrandChild2) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<NormalGrandChild2> for Parent { @@ -820,18 +847,18 @@ impl From<NormalGrandChild2> for AliasChild { } } impl TryFrom<Parent> for NormalGrandChild2 { - type Error = Error; - fn try_from(packet: Parent) -> Result<NormalGrandChild2> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<NormalGrandChild2, Self::Error> { NormalGrandChild2::new(packet.parent) } } impl NormalGrandChild2 { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -843,11 +870,11 @@ impl NormalGrandChild2 { NormalGrandChild2DataChild::None => NormalGrandChild2Child::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let aliaschild = match &parent.child { ParentDataChild::AliasChild(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::AliasChild), actual: format!("{:?}", & parent.child), }); @@ -856,7 +883,7 @@ impl NormalGrandChild2 { let normalgrandchild2 = match &aliaschild.child { AliasChildDataChild::NormalGrandChild2(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(AliasChildDataChild::NormalGrandChild2), actual: format!("{:?}", & aliaschild.child), }); @@ -877,7 +904,7 @@ impl NormalGrandChild2 { NormalGrandChild2DataChild::None => &[], } } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.normalgrandchild2.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_parent_with_no_payload_big_endian.rs b/tests/generated/rust_legacy/packet_decl_parent_with_no_payload_big_endian.rs index 4bb083b..a457c0a 100644 --- a/tests/generated/packet_decl_parent_with_no_payload_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_parent_with_no_payload_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -27,7 +32,7 @@ pub enum Enum8 { } impl TryFrom<u8> for Enum8 { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(Enum8::A), _ => Err(value), @@ -121,25 +126,25 @@ impl ParentData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Parent".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Parent", wanted: 1, got: bytes.get().remaining(), }); } let v = Enum8::try_from(bytes.get_mut().get_u8()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Parent".to_string(), - field: "v".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "v", value: unknown_val as u64, - type_: "Enum8".to_string(), + type_: "Enum8", })?; let payload: &[u8] = &[]; let child = match (v) { @@ -155,8 +160,9 @@ impl ParentData { }; Ok(Self { v, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(u8::from(self.v)); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -166,32 +172,35 @@ impl ParentData { } } impl Packet for Parent { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Parent> for Bytes { - fn from(packet: Parent) -> Self { - packet.to_bytes() +impl TryFrom<Parent> for Bytes { + type Error = EncodeError; + fn try_from(packet: Parent) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Parent> for Vec<u8> { - fn from(packet: Parent) -> Self { - packet.to_vec() +impl TryFrom<Parent> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Parent) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Parent { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -204,13 +213,13 @@ impl Parent { ParentDataChild::None => ParentChild::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { Ok(Self { parent }) } pub fn get_v(&self) -> Enum8 { self.parent.v } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.parent.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -249,15 +258,17 @@ impl ChildData { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { Ok(Self {}) } - fn write_to(&self, buffer: &mut BytesMut) {} + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { + Ok(()) + } fn get_total_size(&self) -> usize { self.get_size() } @@ -266,23 +277,26 @@ impl ChildData { } } impl Packet for Child { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Child> for Bytes { - fn from(packet: Child) -> Self { - packet.to_bytes() +impl TryFrom<Child> for Bytes { + type Error = EncodeError; + fn try_from(packet: Child) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Child> for Vec<u8> { - fn from(packet: Child) -> Self { - packet.to_vec() +impl TryFrom<Child> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Child) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<Child> for Parent { @@ -291,26 +305,26 @@ impl From<Child> for Parent { } } impl TryFrom<Parent> for Child { - type Error = Error; - fn try_from(packet: Parent) -> Result<Child> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<Child, Self::Error> { Child::new(packet.parent) } } impl Child { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let child = match &parent.child { ParentDataChild::Child(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::Child), actual: format!("{:?}", & parent.child), }); @@ -321,7 +335,7 @@ impl Child { pub fn get_v(&self) -> Enum8 { self.parent.v } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.child.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_parent_with_no_payload_little_endian.rs b/tests/generated/rust_legacy/packet_decl_parent_with_no_payload_little_endian.rs index 4bb083b..a457c0a 100644 --- a/tests/generated/packet_decl_parent_with_no_payload_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_parent_with_no_payload_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[repr(u64)] #[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -27,7 +32,7 @@ pub enum Enum8 { } impl TryFrom<u8> for Enum8 { type Error = u8; - fn try_from(value: u8) -> std::result::Result<Self, Self::Error> { + fn try_from(value: u8) -> Result<Self, Self::Error> { match value { 0x0 => Ok(Enum8::A), _ => Err(value), @@ -121,25 +126,25 @@ impl ParentData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Parent".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Parent", wanted: 1, got: bytes.get().remaining(), }); } let v = Enum8::try_from(bytes.get_mut().get_u8()) - .map_err(|unknown_val| Error::InvalidEnumValueError { - obj: "Parent".to_string(), - field: "v".to_string(), + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "v", value: unknown_val as u64, - type_: "Enum8".to_string(), + type_: "Enum8", })?; let payload: &[u8] = &[]; let child = match (v) { @@ -155,8 +160,9 @@ impl ParentData { }; Ok(Self { v, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(u8::from(self.v)); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -166,32 +172,35 @@ impl ParentData { } } impl Packet for Parent { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Parent> for Bytes { - fn from(packet: Parent) -> Self { - packet.to_bytes() +impl TryFrom<Parent> for Bytes { + type Error = EncodeError; + fn try_from(packet: Parent) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Parent> for Vec<u8> { - fn from(packet: Parent) -> Self { - packet.to_vec() +impl TryFrom<Parent> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Parent) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Parent { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } @@ -204,13 +213,13 @@ impl Parent { ParentDataChild::None => ParentChild::None, } } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { Ok(Self { parent }) } pub fn get_v(&self) -> Enum8 { self.parent.v } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.parent.write_to(buffer) } pub fn get_size(&self) -> usize { @@ -249,15 +258,17 @@ impl ChildData { fn conforms(bytes: &[u8]) -> bool { true } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { Ok(Self {}) } - fn write_to(&self, buffer: &mut BytesMut) {} + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { + Ok(()) + } fn get_total_size(&self) -> usize { self.get_size() } @@ -266,23 +277,26 @@ impl ChildData { } } impl Packet for Child { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.parent.get_size()); - self.parent.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.parent.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Child> for Bytes { - fn from(packet: Child) -> Self { - packet.to_bytes() +impl TryFrom<Child> for Bytes { + type Error = EncodeError; + fn try_from(packet: Child) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Child> for Vec<u8> { - fn from(packet: Child) -> Self { - packet.to_vec() +impl TryFrom<Child> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Child) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl From<Child> for Parent { @@ -291,26 +305,26 @@ impl From<Child> for Parent { } } impl TryFrom<Parent> for Child { - type Error = Error; - fn try_from(packet: Parent) -> Result<Child> { + type Error = DecodeError; + fn try_from(packet: Parent) -> Result<Child, Self::Error> { Child::new(packet.parent) } } impl Child { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = ParentData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(parent: ParentData) -> Result<Self> { + fn new(parent: ParentData) -> Result<Self, DecodeError> { let child = match &parent.child { ParentDataChild::Child(value) => value.clone(), _ => { - return Err(Error::InvalidChildError { + return Err(DecodeError::InvalidChildError { expected: stringify!(ParentDataChild::Child), actual: format!("{:?}", & parent.child), }); @@ -321,7 +335,7 @@ impl Child { pub fn get_v(&self) -> Enum8 { self.parent.v } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.child.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_payload_field_unknown_size_big_endian.rs b/tests/generated/rust_legacy/packet_decl_payload_field_unknown_size_big_endian.rs index bfbffe7..c5fdf91 100644 --- a/tests/generated/packet_decl_payload_field_unknown_size_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_payload_field_unknown_size_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum FooDataChild { @@ -60,15 +65,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 3 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); @@ -84,15 +89,21 @@ impl FooData { }; Ok(Self { a, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.a > 0xff_ffff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "a", self.a, 0xff_ffff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a as u64, + maximum_value: 0xff_ffff, + }); } buffer.put_uint(self.a as u64, 3); match &self.child { FooDataChild::Payload(payload) => buffer.put_slice(payload), FooDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -102,32 +113,35 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } @@ -137,7 +151,7 @@ impl Foo { FooDataChild::None => FooChild::None, } } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_a(&self) -> u32 { @@ -149,7 +163,7 @@ impl Foo { FooDataChild::None => &[], } } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_payload_field_unknown_size_little_endian.rs b/tests/generated/rust_legacy/packet_decl_payload_field_unknown_size_little_endian.rs index e473774..43cbfa1 100644 --- a/tests/generated/packet_decl_payload_field_unknown_size_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_payload_field_unknown_size_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum FooDataChild { @@ -60,15 +65,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 3 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); @@ -84,15 +89,21 @@ impl FooData { }; Ok(Self { a, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.a > 0xff_ffff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "a", self.a, 0xff_ffff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a as u64, + maximum_value: 0xff_ffff, + }); } buffer.put_uint_le(self.a as u64, 3); match &self.child { FooDataChild::Payload(payload) => buffer.put_slice(payload), FooDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -102,32 +113,35 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } @@ -137,7 +151,7 @@ impl Foo { FooDataChild::None => FooChild::None, } } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_a(&self) -> u32 { @@ -149,7 +163,7 @@ impl Foo { FooDataChild::None => &[], } } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_payload_field_unknown_size_terminal_big_endian.rs b/tests/generated/rust_legacy/packet_decl_payload_field_unknown_size_terminal_big_endian.rs index c37ff2b..0c1f2e9 100644 --- a/tests/generated/packet_decl_payload_field_unknown_size_terminal_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_payload_field_unknown_size_terminal_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum FooDataChild { @@ -60,15 +65,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 3 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); @@ -76,8 +81,8 @@ impl FooData { let payload = &bytes.get()[..bytes.get().len() - 3]; bytes.get_mut().advance(payload.len()); if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); @@ -91,15 +96,21 @@ impl FooData { }; Ok(Self { a, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { match &self.child { FooDataChild::Payload(payload) => buffer.put_slice(payload), FooDataChild::None => {} } if self.a > 0xff_ffff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "a", self.a, 0xff_ffff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a as u64, + maximum_value: 0xff_ffff, + }); } buffer.put_uint(self.a as u64, 3); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -109,32 +120,35 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } @@ -144,7 +158,7 @@ impl Foo { FooDataChild::None => FooChild::None, } } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_a(&self) -> u32 { @@ -156,7 +170,7 @@ impl Foo { FooDataChild::None => &[], } } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_payload_field_unknown_size_terminal_little_endian.rs b/tests/generated/rust_legacy/packet_decl_payload_field_unknown_size_terminal_little_endian.rs index 2e22410..29da976 100644 --- a/tests/generated/packet_decl_payload_field_unknown_size_terminal_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_payload_field_unknown_size_terminal_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum FooDataChild { @@ -60,15 +65,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 3 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); @@ -76,8 +81,8 @@ impl FooData { let payload = &bytes.get()[..bytes.get().len() - 3]; bytes.get_mut().advance(payload.len()); if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); @@ -91,15 +96,21 @@ impl FooData { }; Ok(Self { a, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { match &self.child { FooDataChild::Payload(payload) => buffer.put_slice(payload), FooDataChild::None => {} } if self.a > 0xff_ffff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "a", self.a, 0xff_ffff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a as u64, + maximum_value: 0xff_ffff, + }); } buffer.put_uint_le(self.a as u64, 3); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -109,32 +120,35 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } @@ -144,7 +158,7 @@ impl Foo { FooDataChild::None => FooChild::None, } } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_a(&self) -> u32 { @@ -156,7 +170,7 @@ impl Foo { FooDataChild::None => &[], } } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_payload_field_variable_size_big_endian.rs b/tests/generated/rust_legacy/packet_decl_payload_field_variable_size_big_endian.rs index 5df7232..164875c 100644 --- a/tests/generated/packet_decl_payload_field_variable_size_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_payload_field_variable_size_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum FooDataChild { @@ -62,31 +67,31 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 4 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); } let a = bytes.get_mut().get_u8(); if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); } let payload_size = bytes.get_mut().get_u8() as usize; if bytes.get().remaining() < payload_size { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: payload_size, got: bytes.get().remaining(), }); @@ -94,8 +99,8 @@ impl FooData { let payload = &bytes.get()[..payload_size]; bytes.get_mut().advance(payload_size); if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 2, got: bytes.get().remaining(), }); @@ -109,13 +114,15 @@ impl FooData { }; Ok(Self { a, b, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(self.a); if self.child.get_total_size() > 0xff { - panic!( - "Invalid length for {}::{}: {} > {}", "Foo", "_payload_", self.child - .get_total_size(), 0xff - ); + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: self.child.get_total_size(), + maximum_size: 0xff, + }); } buffer.put_u8(self.child.get_total_size() as u8); match &self.child { @@ -123,6 +130,7 @@ impl FooData { FooDataChild::None => {} } buffer.put_u16(self.b); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -132,32 +140,35 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } @@ -167,7 +178,7 @@ impl Foo { FooDataChild::None => FooChild::None, } } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_a(&self) -> u8 { @@ -182,7 +193,7 @@ impl Foo { FooDataChild::None => &[], } } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_payload_field_variable_size_little_endian.rs b/tests/generated/rust_legacy/packet_decl_payload_field_variable_size_little_endian.rs index 477c8b6..ff77f86 100644 --- a/tests/generated/packet_decl_payload_field_variable_size_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_payload_field_variable_size_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum FooDataChild { @@ -62,31 +67,31 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 4 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); } let a = bytes.get_mut().get_u8(); if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); } let payload_size = bytes.get_mut().get_u8() as usize; if bytes.get().remaining() < payload_size { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: payload_size, got: bytes.get().remaining(), }); @@ -94,8 +99,8 @@ impl FooData { let payload = &bytes.get()[..payload_size]; bytes.get_mut().advance(payload_size); if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 2, got: bytes.get().remaining(), }); @@ -109,13 +114,15 @@ impl FooData { }; Ok(Self { a, b, child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(self.a); if self.child.get_total_size() > 0xff { - panic!( - "Invalid length for {}::{}: {} > {}", "Foo", "_payload_", self.child - .get_total_size(), 0xff - ); + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: self.child.get_total_size(), + maximum_size: 0xff, + }); } buffer.put_u8(self.child.get_total_size() as u8); match &self.child { @@ -123,6 +130,7 @@ impl FooData { FooDataChild::None => {} } buffer.put_u16_le(self.b); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -132,32 +140,35 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } @@ -167,7 +178,7 @@ impl Foo { FooDataChild::None => FooChild::None, } } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_a(&self) -> u8 { @@ -182,7 +193,7 @@ impl Foo { FooDataChild::None => &[], } } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_reserved_field_big_endian.rs b/tests/generated/rust_legacy/packet_decl_reserved_field_big_endian.rs index b296e58..288680c 100644 --- a/tests/generated/packet_decl_reserved_field_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_reserved_field_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData {} @@ -34,15 +39,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 5 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 5, got: bytes.get().remaining(), }); @@ -50,8 +55,9 @@ impl FooData { bytes.get_mut().advance(5); Ok(Self {}) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_bytes(0, 5); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -61,39 +67,42 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_reserved_field_little_endian.rs b/tests/generated/rust_legacy/packet_decl_reserved_field_little_endian.rs index b296e58..288680c 100644 --- a/tests/generated/packet_decl_reserved_field_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_reserved_field_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData {} @@ -34,15 +39,15 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 5 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 5 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 5, got: bytes.get().remaining(), }); @@ -50,8 +55,9 @@ impl FooData { bytes.get_mut().advance(5); Ok(Self {}) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_bytes(0, 5); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -61,39 +67,42 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_simple_scalars_big_endian.rs b/tests/generated/rust_legacy/packet_decl_simple_scalars_big_endian.rs index 8c31583..f538606 100644 --- a/tests/generated/packet_decl_simple_scalars_big_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_simple_scalars_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -42,31 +47,31 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 6 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); } let x = bytes.get_mut().get_u8(); if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 2, got: bytes.get().remaining(), }); } let y = bytes.get_mut().get_u16(); if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); @@ -74,13 +79,19 @@ impl FooData { let z = bytes.get_mut().get_uint(3) as u32; Ok(Self { x, y, z }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(self.x); buffer.put_u16(self.y); if self.z > 0xff_ffff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "z", self.z, 0xff_ffff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "z", + value: self.z as u64, + maximum_value: 0xff_ffff, + }); } buffer.put_uint(self.z as u64, 3); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -90,36 +101,39 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_x(&self) -> u8 { @@ -131,7 +145,7 @@ impl Foo { pub fn get_z(&self) -> u32 { self.foo.z } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/packet_decl_simple_scalars_little_endian.rs b/tests/generated/rust_legacy/packet_decl_simple_scalars_little_endian.rs index d1c3655..fccc759 100644 --- a/tests/generated/packet_decl_simple_scalars_little_endian.rs +++ b/tests/generated/rust_legacy/packet_decl_simple_scalars_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FooData { @@ -42,31 +47,31 @@ impl FooData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 6 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 1, got: bytes.get().remaining(), }); } let x = bytes.get_mut().get_u8(); if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 2, got: bytes.get().remaining(), }); } let y = bytes.get_mut().get_u16_le(); if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); @@ -74,13 +79,19 @@ impl FooData { let z = bytes.get_mut().get_uint_le(3) as u32; Ok(Self { x, y, z }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(self.x); buffer.put_u16_le(self.y); if self.z > 0xff_ffff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "z", self.z, 0xff_ffff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "z", + value: self.z as u64, + maximum_value: 0xff_ffff, + }); } buffer.put_uint_le(self.z as u64, 3); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -90,36 +101,39 @@ impl FooData { } } impl Packet for Foo { - fn to_bytes(self) -> Bytes { - let mut buffer = BytesMut::with_capacity(self.foo.get_size()); - self.foo.write_to(&mut buffer); - buffer.freeze() + fn encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.foo.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Foo> for Bytes { - fn from(packet: Foo) -> Self { - packet.to_bytes() +impl TryFrom<Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Foo> for Vec<u8> { - fn from(packet: Foo) -> Self { - packet.to_vec() +impl TryFrom<Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Foo { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = FooData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(foo: FooData) -> Result<Self> { + fn new(foo: FooData) -> Result<Self, DecodeError> { Ok(Self { foo }) } pub fn get_x(&self) -> u8 { @@ -131,7 +145,7 @@ impl Foo { pub fn get_z(&self) -> u32 { self.foo.z } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.foo.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/payload_with_size_modifier_big_endian.rs b/tests/generated/rust_legacy/payload_with_size_modifier_big_endian.rs index beec02b..b0c4277 100644 --- a/tests/generated/payload_with_size_modifier_big_endian.rs +++ b/tests/generated/rust_legacy/payload_with_size_modifier_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum TestDataChild { @@ -58,31 +63,31 @@ impl TestData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Test".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Test", wanted: 1, got: bytes.get().remaining(), }); } let payload_size = bytes.get_mut().get_u8() as usize; if payload_size < 1 { - return Err(Error::InvalidLengthError { - obj: "Test".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Test", wanted: 1, got: payload_size, }); } let payload_size = payload_size - 1; if bytes.get().remaining() < payload_size { - return Err(Error::InvalidLengthError { - obj: "Test".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Test", wanted: payload_size, got: bytes.get().remaining(), }); @@ -97,18 +102,21 @@ impl TestData { }; Ok(Self { child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if (self.child.get_total_size() + 1) > 0xff { - panic!( - "Invalid length for {}::{}: {} > {}", "Test", "_payload_", (self.child - .get_total_size() + 1), 0xff - ); + return Err(EncodeError::SizeOverflow { + packet: "Test", + field: "_payload_", + size: (self.child.get_total_size() + 1), + maximum_size: 0xff, + }); } buffer.put_u8((self.child.get_total_size() + 1) as u8); match &self.child { TestDataChild::Payload(payload) => buffer.put_slice(payload), TestDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -118,32 +126,35 @@ impl TestData { } } 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 encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.test.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Test> for Bytes { - fn from(packet: Test) -> Self { - packet.to_bytes() +impl TryFrom<Test> for Bytes { + type Error = EncodeError; + fn try_from(packet: Test) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Test> for Vec<u8> { - fn from(packet: Test) -> Self { - packet.to_vec() +impl TryFrom<Test> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Test) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Test { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = TestData::parse_inner(&mut bytes)?; Self::new(data) } @@ -153,7 +164,7 @@ impl Test { TestDataChild::None => TestChild::None, } } - fn new(test: TestData) -> Result<Self> { + fn new(test: TestData) -> Result<Self, DecodeError> { Ok(Self { test }) } pub fn get_payload(&self) -> &[u8] { @@ -162,7 +173,7 @@ impl Test { TestDataChild::None => &[], } } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.test.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/payload_with_size_modifier_little_endian.rs b/tests/generated/rust_legacy/payload_with_size_modifier_little_endian.rs index beec02b..b0c4277 100644 --- a/tests/generated/payload_with_size_modifier_little_endian.rs +++ b/tests/generated/rust_legacy/payload_with_size_modifier_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum TestDataChild { @@ -58,31 +63,31 @@ impl TestData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Test".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Test", wanted: 1, got: bytes.get().remaining(), }); } let payload_size = bytes.get_mut().get_u8() as usize; if payload_size < 1 { - return Err(Error::InvalidLengthError { - obj: "Test".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Test", wanted: 1, got: payload_size, }); } let payload_size = payload_size - 1; if bytes.get().remaining() < payload_size { - return Err(Error::InvalidLengthError { - obj: "Test".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Test", wanted: payload_size, got: bytes.get().remaining(), }); @@ -97,18 +102,21 @@ impl TestData { }; Ok(Self { child }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if (self.child.get_total_size() + 1) > 0xff { - panic!( - "Invalid length for {}::{}: {} > {}", "Test", "_payload_", (self.child - .get_total_size() + 1), 0xff - ); + return Err(EncodeError::SizeOverflow { + packet: "Test", + field: "_payload_", + size: (self.child.get_total_size() + 1), + maximum_size: 0xff, + }); } buffer.put_u8((self.child.get_total_size() + 1) as u8); match &self.child { TestDataChild::Payload(payload) => buffer.put_slice(payload), TestDataChild::None => {} } + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -118,32 +126,35 @@ impl TestData { } } 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 encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.test.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Test> for Bytes { - fn from(packet: Test) -> Self { - packet.to_bytes() +impl TryFrom<Test> for Bytes { + type Error = EncodeError; + fn try_from(packet: Test) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Test> for Vec<u8> { - fn from(packet: Test) -> Self { - packet.to_vec() +impl TryFrom<Test> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Test) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Test { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = TestData::parse_inner(&mut bytes)?; Self::new(data) } @@ -153,7 +164,7 @@ impl Test { TestDataChild::None => TestChild::None, } } - fn new(test: TestData) -> Result<Self> { + fn new(test: TestData) -> Result<Self, DecodeError> { Ok(Self { test }) } pub fn get_payload(&self) -> &[u8] { @@ -162,7 +173,7 @@ impl Test { TestDataChild::None => &[], } } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.test.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/rust_legacy/preamble.rs b/tests/generated/rust_legacy/preamble.rs new file mode 100644 index 0000000..ab77b58 --- /dev/null +++ b/tests/generated/rust_legacy/preamble.rs @@ -0,0 +1,25 @@ +#![rustfmt::skip] +/// @generated rust packets from foo.pdl. +use bytes::{Buf, BufMut, Bytes, BytesMut}; +use std::convert::{TryFrom, TryInto}; +use std::cell::Cell; +use std::fmt; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} diff --git a/tests/generated/reserved_identifier_big_endian.rs b/tests/generated/rust_legacy/reserved_identifier_big_endian.rs index f346dd1..4fce5c3 100644 --- a/tests/generated/reserved_identifier_big_endian.rs +++ b/tests/generated/rust_legacy/reserved_identifier_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TestData { @@ -38,15 +43,15 @@ impl TestData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Test".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Test", wanted: 1, got: bytes.get().remaining(), }); @@ -54,8 +59,9 @@ impl TestData { let r#type = bytes.get_mut().get_u8(); Ok(Self { r#type }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(self.r#type); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -65,42 +71,45 @@ impl TestData { } } 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 encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.test.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Test> for Bytes { - fn from(packet: Test) -> Self { - packet.to_bytes() +impl TryFrom<Test> for Bytes { + type Error = EncodeError; + fn try_from(packet: Test) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Test> for Vec<u8> { - fn from(packet: Test) -> Self { - packet.to_vec() +impl TryFrom<Test> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Test) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Test { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = TestData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(test: TestData) -> Result<Self> { + fn new(test: TestData) -> Result<Self, DecodeError> { Ok(Self { test }) } pub fn get_type(&self) -> u8 { self.test.r#type } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.test.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/reserved_identifier_little_endian.rs b/tests/generated/rust_legacy/reserved_identifier_little_endian.rs index f346dd1..4fce5c3 100644 --- a/tests/generated/reserved_identifier_little_endian.rs +++ b/tests/generated/rust_legacy/reserved_identifier_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TestData { @@ -38,15 +43,15 @@ impl TestData { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 1 } - fn parse(bytes: &[u8]) -> Result<Self> { + fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 1 { - return Err(Error::InvalidLengthError { - obj: "Test".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Test", wanted: 1, got: bytes.get().remaining(), }); @@ -54,8 +59,9 @@ impl TestData { let r#type = bytes.get_mut().get_u8(); Ok(Self { r#type }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { buffer.put_u8(self.r#type); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() @@ -65,42 +71,45 @@ impl TestData { } } 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 encoded_len(&self) -> usize { + self.get_size() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + self.test.write_to(buf) } - fn to_vec(self) -> Vec<u8> { - self.to_bytes().to_vec() + fn decode(_: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + unimplemented!("Rust legacy does not implement full packet trait") } } -impl From<Test> for Bytes { - fn from(packet: Test) -> Self { - packet.to_bytes() +impl TryFrom<Test> for Bytes { + type Error = EncodeError; + fn try_from(packet: Test) -> Result<Self, Self::Error> { + packet.encode_to_bytes() } } -impl From<Test> for Vec<u8> { - fn from(packet: Test) -> Self { - packet.to_vec() +impl TryFrom<Test> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: Test) -> Result<Self, Self::Error> { + packet.encode_to_vec() } } impl Test { - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { let data = TestData::parse_inner(&mut bytes)?; Self::new(data) } - fn new(test: TestData) -> Result<Self> { + fn new(test: TestData) -> Result<Self, DecodeError> { Ok(Self { test }) } pub fn get_type(&self) -> u8 { self.test.r#type } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to(&self, buffer: &mut impl BufMut) -> Result<(), EncodeError> { self.test.write_to(buffer) } pub fn get_size(&self) -> usize { diff --git a/tests/generated/struct_decl_complex_scalars_big_endian.rs b/tests/generated/rust_legacy/struct_decl_complex_scalars_big_endian.rs index 5fa18cd..42b0858 100644 --- a/tests/generated/struct_decl_complex_scalars_big_endian.rs +++ b/tests/generated/rust_legacy/struct_decl_complex_scalars_big_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Foo { @@ -32,15 +37,15 @@ impl Foo { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 7 } - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 2, got: bytes.get().remaining(), }); @@ -50,16 +55,16 @@ impl Foo { let b = (chunk >> 3) as u8; let c = ((chunk >> 11) & 0x1f) as u8; if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); } let d = bytes.get_mut().get_uint(3) as u32; if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 2, got: bytes.get().remaining(), }); @@ -69,27 +74,53 @@ impl Foo { let f = ((chunk >> 12) & 0xf) as u8; Ok(Self { a, b, c, d, e, f }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.a > 0x7 { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "a", self.a, 0x7); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a as u64, + maximum_value: 0x7, + }); } if self.c > 0x1f { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "c", self.c, 0x1f); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "c", + value: self.c as u64, + maximum_value: 0x1f, + }); } let value = (self.a as u16) | ((self.b as u16) << 3) | ((self.c as u16) << 11); buffer.put_u16(value); if self.d > 0xff_ffff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "d", self.d, 0xff_ffff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "d", + value: self.d as u64, + maximum_value: 0xff_ffff, + }); } buffer.put_uint(self.d as u64, 3); if self.e > 0xfff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "e", self.e, 0xfff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "e", + value: self.e as u64, + maximum_value: 0xfff, + }); } if self.f > 0xf { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "f", self.f, 0xf); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "f", + value: self.f as u64, + maximum_value: 0xf, + }); } let value = self.e | ((self.f as u16) << 12); buffer.put_u16(value); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() diff --git a/tests/generated/struct_decl_complex_scalars_little_endian.rs b/tests/generated/rust_legacy/struct_decl_complex_scalars_little_endian.rs index dbd7b69..a8c3f7a 100644 --- a/tests/generated/struct_decl_complex_scalars_little_endian.rs +++ b/tests/generated/rust_legacy/struct_decl_complex_scalars_little_endian.rs @@ -4,13 +4,13 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use std::convert::{TryFrom, TryInto}; use std::cell::Cell; use std::fmt; -use pdl_runtime::{Error, Packet}; -type Result<T> = std::result::Result<T, Error>; +use std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; /// 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)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Private<T>(T); impl<T> std::ops::Deref for Private<T> { type Target = T; @@ -18,6 +18,11 @@ impl<T> std::ops::Deref for Private<T> { &self.0 } } +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Foo { @@ -32,15 +37,15 @@ impl Foo { fn conforms(bytes: &[u8]) -> bool { bytes.len() >= 7 } - pub fn parse(bytes: &[u8]) -> Result<Self> { + pub fn parse(bytes: &[u8]) -> Result<Self, DecodeError> { 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> { + fn parse_inner(mut bytes: &mut Cell<&[u8]>) -> Result<Self, DecodeError> { if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 2, got: bytes.get().remaining(), }); @@ -50,16 +55,16 @@ impl Foo { let b = (chunk >> 3) as u8; let c = ((chunk >> 11) & 0x1f) as u8; if bytes.get().remaining() < 3 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 3, got: bytes.get().remaining(), }); } let d = bytes.get_mut().get_uint_le(3) as u32; if bytes.get().remaining() < 2 { - return Err(Error::InvalidLengthError { - obj: "Foo".to_string(), + return Err(DecodeError::InvalidLengthError { + obj: "Foo", wanted: 2, got: bytes.get().remaining(), }); @@ -69,27 +74,53 @@ impl Foo { let f = ((chunk >> 12) & 0xf) as u8; Ok(Self { a, b, c, d, e, f }) } - fn write_to(&self, buffer: &mut BytesMut) { + fn write_to<T: BufMut>(&self, buffer: &mut T) -> Result<(), EncodeError> { if self.a > 0x7 { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "a", self.a, 0x7); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "a", + value: self.a as u64, + maximum_value: 0x7, + }); } if self.c > 0x1f { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "c", self.c, 0x1f); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "c", + value: self.c as u64, + maximum_value: 0x1f, + }); } let value = (self.a as u16) | ((self.b as u16) << 3) | ((self.c as u16) << 11); buffer.put_u16_le(value); if self.d > 0xff_ffff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "d", self.d, 0xff_ffff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "d", + value: self.d as u64, + maximum_value: 0xff_ffff, + }); } buffer.put_uint_le(self.d as u64, 3); if self.e > 0xfff { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "e", self.e, 0xfff); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "e", + value: self.e as u64, + maximum_value: 0xfff, + }); } if self.f > 0xf { - panic!("Invalid value for {}::{}: {} > {}", "Foo", "f", self.f, 0xf); + return Err(EncodeError::InvalidScalarValue { + packet: "Foo", + field: "f", + value: self.f as u64, + maximum_value: 0xf, + }); } let value = self.e | ((self.f as u16) << 12); buffer.put_u16_le(value); + Ok(()) } fn get_total_size(&self) -> usize { self.get_size() diff --git a/tests/generated/struct_decl_child_structs_big_endian.rs b/tests/generated/struct_decl_child_structs_big_endian.rs new file mode 100644 index 0000000..2fda403 --- /dev/null +++ b/tests/generated/struct_decl_child_structs_big_endian.rs @@ -0,0 +1,369 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u16", into = "u16"))] +pub enum Enum16 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u16> for Enum16 { + type Error = u16; + fn try_from(value: u16) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum16::A), + 0x2 => Ok(Enum16::B), + _ => Err(value), + } + } +} +impl From<&Enum16> for u16 { + fn from(value: &Enum16) -> Self { + match value { + Enum16::A => 0x1, + Enum16::B => 0x2, + } + } +} +impl From<Enum16> for u16 { + fn from(value: Enum16) -> Self { + (&value).into() + } +} +impl From<Enum16> for i32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for i64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u8, + pub b: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: &Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() + } +} +impl TryFrom<&Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: &Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum FooChild { + Bar(Bar), + Baz(Baz), + None, +} +impl Foo { + pub fn specialize(&self) -> Result<FooChild, DecodeError> { + Ok( + match (self.a, self.b) { + (100, _) => FooChild::Bar(self.try_into()?), + (_, Enum16::B) => FooChild::Baz(self.try_into()?), + _ => FooChild::None, + }, + ) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> Enum16 { + self.b + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 4 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16(u16::from(self.b())); + if self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(self.payload.len() as u8); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let a = buf.get_u8(); + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let b = Enum16::try_from(buf.get_u16()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "b", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + let payload = Vec::from(payload); + Ok((Self { payload, a, b }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: u8, + pub b: Enum16, +} +impl TryFrom<&Foo> for Bar { + type Error = DecodeError; + fn try_from(parent: &Foo) -> Result<Bar, Self::Error> { + Bar::decode_partial(&parent) + } +} +impl TryFrom<&Bar> for Foo { + type Error = EncodeError; + fn try_from(packet: &Bar) -> Result<Foo, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Foo { + a: 100, + b: packet.b, + payload, + }) + } +} +impl TryFrom<&Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: &Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() + } +} +impl TryFrom<&Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: &Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() + } +} +impl Bar { + fn decode_partial(parent: &Foo) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let x = buf.get_u8(); + if buf.is_empty() { + Ok(Self { x, b: parent.b }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.x()); + Ok(()) + } + pub fn x(&self) -> u8 { + self.x + } + pub fn b(&self) -> Enum16 { + self.b + } + pub fn a(&self) -> u8 { + 100 + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 5 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16(u16::from(self.b())); + if 1 > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: 1, + maximum_size: 0xff, + }); + } + buf.put_u8(1 as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Foo::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Baz { + pub y: u16, + pub a: u8, +} +impl TryFrom<&Foo> for Baz { + type Error = DecodeError; + fn try_from(parent: &Foo) -> Result<Baz, Self::Error> { + Baz::decode_partial(&parent) + } +} +impl TryFrom<&Baz> for Foo { + type Error = EncodeError; + fn try_from(packet: &Baz) -> Result<Foo, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Foo { + a: packet.a, + b: Enum16::B, + payload, + }) + } +} +impl TryFrom<&Baz> for Bytes { + type Error = EncodeError; + fn try_from(packet: &Baz) -> Result<Self, Self::Error> { + packet.encode_to_bytes() + } +} +impl TryFrom<&Baz> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: &Baz) -> Result<Self, Self::Error> { + packet.encode_to_vec() + } +} +impl Baz { + fn decode_partial(parent: &Foo) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Baz", + wanted: 2, + got: buf.remaining(), + }); + } + let y = buf.get_u16(); + if buf.is_empty() { + Ok(Self { y, a: parent.a }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(self.y()); + Ok(()) + } + pub fn y(&self) -> u16 { + self.y + } + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> Enum16 { + Enum16::B + } +} +impl Packet for Baz { + fn encoded_len(&self) -> usize { + 6 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16(u16::from(self.b())); + if 2 > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: 2, + maximum_size: 0xff, + }); + } + buf.put_u8(2 as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Foo::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/generated/struct_decl_child_structs_little_endian.rs b/tests/generated/struct_decl_child_structs_little_endian.rs new file mode 100644 index 0000000..09bf722 --- /dev/null +++ b/tests/generated/struct_decl_child_structs_little_endian.rs @@ -0,0 +1,369 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u16", into = "u16"))] +pub enum Enum16 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u16> for Enum16 { + type Error = u16; + fn try_from(value: u16) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum16::A), + 0x2 => Ok(Enum16::B), + _ => Err(value), + } + } +} +impl From<&Enum16> for u16 { + fn from(value: &Enum16) -> Self { + match value { + Enum16::A => 0x1, + Enum16::B => 0x2, + } + } +} +impl From<Enum16> for u16 { + fn from(value: Enum16) -> Self { + (&value).into() + } +} +impl From<Enum16> for i32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for i64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Foo { + pub a: u8, + pub b: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Foo> for Bytes { + type Error = EncodeError; + fn try_from(packet: &Foo) -> Result<Self, Self::Error> { + packet.encode_to_bytes() + } +} +impl TryFrom<&Foo> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: &Foo) -> Result<Self, Self::Error> { + packet.encode_to_vec() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum FooChild { + Bar(Bar), + Baz(Baz), + None, +} +impl Foo { + pub fn specialize(&self) -> Result<FooChild, DecodeError> { + Ok( + match (self.a, self.b) { + (100, _) => FooChild::Bar(self.try_into()?), + (_, Enum16::B) => FooChild::Baz(self.try_into()?), + _ => FooChild::None, + }, + ) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> Enum16 { + self.b + } +} +impl Packet for Foo { + fn encoded_len(&self) -> usize { + 4 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16_le(u16::from(self.b())); + if self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(self.payload.len() as u8); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let a = buf.get_u8(); + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 2, + got: buf.remaining(), + }); + } + let b = Enum16::try_from(buf.get_u16_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Foo", + field: "b", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Foo", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + let payload = Vec::from(payload); + Ok((Self { payload, a, b }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bar { + pub x: u8, + pub b: Enum16, +} +impl TryFrom<&Foo> for Bar { + type Error = DecodeError; + fn try_from(parent: &Foo) -> Result<Bar, Self::Error> { + Bar::decode_partial(&parent) + } +} +impl TryFrom<&Bar> for Foo { + type Error = EncodeError; + fn try_from(packet: &Bar) -> Result<Foo, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Foo { + a: 100, + b: packet.b, + payload, + }) + } +} +impl TryFrom<&Bar> for Bytes { + type Error = EncodeError; + fn try_from(packet: &Bar) -> Result<Self, Self::Error> { + packet.encode_to_bytes() + } +} +impl TryFrom<&Bar> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: &Bar) -> Result<Self, Self::Error> { + packet.encode_to_vec() + } +} +impl Bar { + fn decode_partial(parent: &Foo) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Bar", + wanted: 1, + got: buf.remaining(), + }); + } + let x = buf.get_u8(); + if buf.is_empty() { + Ok(Self { x, b: parent.b }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.x()); + Ok(()) + } + pub fn x(&self) -> u8 { + self.x + } + pub fn b(&self) -> Enum16 { + self.b + } + pub fn a(&self) -> u8 { + 100 + } +} +impl Packet for Bar { + fn encoded_len(&self) -> usize { + 5 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16_le(u16::from(self.b())); + if 1 > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: 1, + maximum_size: 0xff, + }); + } + buf.put_u8(1 as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Foo::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Baz { + pub y: u16, + pub a: u8, +} +impl TryFrom<&Foo> for Baz { + type Error = DecodeError; + fn try_from(parent: &Foo) -> Result<Baz, Self::Error> { + Baz::decode_partial(&parent) + } +} +impl TryFrom<&Baz> for Foo { + type Error = EncodeError; + fn try_from(packet: &Baz) -> Result<Foo, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Foo { + a: packet.a, + b: Enum16::B, + payload, + }) + } +} +impl TryFrom<&Baz> for Bytes { + type Error = EncodeError; + fn try_from(packet: &Baz) -> Result<Self, Self::Error> { + packet.encode_to_bytes() + } +} +impl TryFrom<&Baz> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: &Baz) -> Result<Self, Self::Error> { + packet.encode_to_vec() + } +} +impl Baz { + fn decode_partial(parent: &Foo) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Baz", + wanted: 2, + got: buf.remaining(), + }); + } + let y = buf.get_u16_le(); + if buf.is_empty() { + Ok(Self { y, a: parent.a }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(self.y()); + Ok(()) + } + pub fn y(&self) -> u16 { + self.y + } + pub fn a(&self) -> u8 { + self.a + } + pub fn b(&self) -> Enum16 { + Enum16::B + } +} +impl Packet for Baz { + fn encoded_len(&self) -> usize { + 6 + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u8(self.a()); + buf.put_u16_le(u16::from(self.b())); + if 2 > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Foo", + field: "_payload_", + size: 2, + maximum_size: 0xff, + }); + } + buf.put_u8(2 as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Foo::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/generated/struct_decl_grand_children_big_endian.rs b/tests/generated/struct_decl_grand_children_big_endian.rs new file mode 100644 index 0000000..0650d32 --- /dev/null +++ b/tests/generated/struct_decl_grand_children_big_endian.rs @@ -0,0 +1,560 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u16", into = "u16"))] +pub enum Enum16 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u16> for Enum16 { + type Error = u16; + fn try_from(value: u16) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum16::A), + 0x2 => Ok(Enum16::B), + _ => Err(value), + } + } +} +impl From<&Enum16> for u16 { + fn from(value: &Enum16) -> Self { + match value { + Enum16::A => 0x1, + Enum16::B => 0x2, + } + } +} +impl From<Enum16> for u16 { + fn from(value: Enum16) -> Self { + (&value).into() + } +} +impl From<Enum16> for i32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for i64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Parent { + pub foo: Enum16, + pub bar: Enum16, + pub baz: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Parent> for Bytes { + type Error = EncodeError; + fn try_from(packet: &Parent) -> Result<Self, Self::Error> { + packet.encode_to_bytes() + } +} +impl TryFrom<&Parent> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: &Parent) -> Result<Self, Self::Error> { + packet.encode_to_vec() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ParentChild { + Child(Child), + None, +} +impl Parent { + pub fn specialize(&self) -> Result<ParentChild, DecodeError> { + Ok( + match (self.foo,) { + (Enum16::A,) => ParentChild::Child(self.try_into()?), + _ => ParentChild::None, + }, + ) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn foo(&self) -> Enum16 { + self.foo + } + pub fn bar(&self) -> Enum16 { + self.bar + } + pub fn baz(&self) -> Enum16 { + self.baz + } +} +impl Packet for Parent { + fn encoded_len(&self) -> usize { + 7 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(u16::from(self.foo())); + buf.put_u16(u16::from(self.bar())); + buf.put_u16(u16::from(self.baz())); + if self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(self.payload.len() as u8); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let foo = Enum16::try_from(buf.get_u16()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "foo", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let bar = Enum16::try_from(buf.get_u16()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "bar", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let baz = Enum16::try_from(buf.get_u16()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "baz", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + let payload = Vec::from(payload); + Ok((Self { payload, foo, bar, baz }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Child { + pub quux: Enum16, + pub bar: Enum16, + pub baz: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Parent> for Child { + type Error = DecodeError; + fn try_from(parent: &Parent) -> Result<Child, Self::Error> { + Child::decode_partial(&parent) + } +} +impl TryFrom<&Child> for Parent { + type Error = EncodeError; + fn try_from(packet: &Child) -> Result<Parent, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Parent { + foo: Enum16::A, + bar: packet.bar, + baz: packet.baz, + payload, + }) + } +} +impl TryFrom<&Child> for Bytes { + type Error = EncodeError; + fn try_from(packet: &Child) -> Result<Self, Self::Error> { + packet.encode_to_bytes() + } +} +impl TryFrom<&Child> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: &Child) -> Result<Self, Self::Error> { + packet.encode_to_vec() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ChildChild { + GrandChild(GrandChild), + None, +} +impl Child { + pub fn specialize(&self) -> Result<ChildChild, DecodeError> { + Ok( + match (self.bar, self.quux) { + (Enum16::A, Enum16::A) => ChildChild::GrandChild(self.try_into()?), + _ => ChildChild::None, + }, + ) + } + fn decode_partial(parent: &Parent) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Child", + wanted: 2, + got: buf.remaining(), + }); + } + let quux = Enum16::try_from(buf.get_u16()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Child", + field: "quux", + value: unknown_val as u64, + type_: "Enum16", + })?; + let payload = buf.to_vec(); + buf.advance(payload.len()); + let payload = Vec::from(payload); + if buf.is_empty() { + Ok(Self { + payload, + quux, + bar: parent.bar, + baz: parent.baz, + }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(u16::from(self.quux())); + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn quux(&self) -> Enum16 { + self.quux + } + pub fn bar(&self) -> Enum16 { + self.bar + } + pub fn baz(&self) -> Enum16 { + self.baz + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for Child { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(u16::from(self.foo())); + buf.put_u16(u16::from(self.bar())); + buf.put_u16(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Parent::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GrandChild { + pub baz: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Child> for GrandChild { + type Error = DecodeError; + fn try_from(parent: &Child) -> Result<GrandChild, Self::Error> { + GrandChild::decode_partial(&parent) + } +} +impl TryFrom<&GrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Child, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Child { + quux: Enum16::A, + bar: Enum16::A, + baz: packet.baz, + payload, + }) + } +} +impl TryFrom<&GrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Parent, Self::Error> { + (&Child::try_from(packet)?).try_into() + } +} +impl TryFrom<&GrandChild> for Bytes { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Self, Self::Error> { + packet.encode_to_bytes() + } +} +impl TryFrom<&GrandChild> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Self, Self::Error> { + packet.encode_to_vec() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum GrandChildChild { + GrandGrandChild(GrandGrandChild), + None, +} +impl GrandChild { + pub fn specialize(&self) -> Result<GrandChildChild, DecodeError> { + Ok( + match (self.baz,) { + (Enum16::A,) => GrandChildChild::GrandGrandChild(self.try_into()?), + _ => GrandChildChild::None, + }, + ) + } + fn decode_partial(parent: &Child) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + let payload = buf.to_vec(); + buf.advance(payload.len()); + let payload = Vec::from(payload); + if buf.is_empty() { + Ok(Self { payload, baz: parent.baz }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn baz(&self) -> Enum16 { + self.baz + } + pub fn quux(&self) -> Enum16 { + Enum16::A + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } + pub fn bar(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for GrandChild { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(u16::from(self.foo())); + buf.put_u16(u16::from(self.bar())); + buf.put_u16(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + buf.put_u16(u16::from(self.quux())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Child::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GrandGrandChild { + pub payload: Vec<u8>, +} +impl TryFrom<&GrandChild> for GrandGrandChild { + type Error = DecodeError; + fn try_from(parent: &GrandChild) -> Result<GrandGrandChild, Self::Error> { + GrandGrandChild::decode_partial(&parent) + } +} +impl TryFrom<&GrandGrandChild> for GrandChild { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<GrandChild, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(GrandChild { + baz: Enum16::A, + payload, + }) + } +} +impl TryFrom<&GrandGrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Child, Self::Error> { + (&GrandChild::try_from(packet)?).try_into() + } +} +impl TryFrom<&GrandGrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Parent, Self::Error> { + (&GrandChild::try_from(packet)?).try_into() + } +} +impl TryFrom<&GrandGrandChild> for Bytes { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Self, Self::Error> { + packet.encode_to_bytes() + } +} +impl TryFrom<&GrandGrandChild> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Self, Self::Error> { + packet.encode_to_vec() + } +} +impl GrandGrandChild { + fn decode_partial(parent: &GrandChild) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + let payload = buf.to_vec(); + buf.advance(payload.len()); + let payload = Vec::from(payload); + if buf.is_empty() { + Ok(Self { payload }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn quux(&self) -> Enum16 { + Enum16::A + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } + pub fn bar(&self) -> Enum16 { + Enum16::A + } + pub fn baz(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for GrandGrandChild { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16(u16::from(self.foo())); + buf.put_u16(u16::from(self.bar())); + buf.put_u16(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + buf.put_u16(u16::from(self.quux())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = GrandChild::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/generated/struct_decl_grand_children_little_endian.rs b/tests/generated/struct_decl_grand_children_little_endian.rs new file mode 100644 index 0000000..eca914a --- /dev/null +++ b/tests/generated/struct_decl_grand_children_little_endian.rs @@ -0,0 +1,560 @@ +#![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 std::result::Result; +use pdl_runtime::{DecodeError, EncodeError, Packet}; +/// 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(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 + } +} +impl<T: std::fmt::Debug> std::fmt::Debug for Private<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + T::fmt(&self.0, f) + } +} +#[repr(u64)] +#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(try_from = "u16", into = "u16"))] +pub enum Enum16 { + A = 0x1, + B = 0x2, +} +impl TryFrom<u16> for Enum16 { + type Error = u16; + fn try_from(value: u16) -> Result<Self, Self::Error> { + match value { + 0x1 => Ok(Enum16::A), + 0x2 => Ok(Enum16::B), + _ => Err(value), + } + } +} +impl From<&Enum16> for u16 { + fn from(value: &Enum16) -> Self { + match value { + Enum16::A => 0x1, + Enum16::B => 0x2, + } + } +} +impl From<Enum16> for u16 { + fn from(value: Enum16) -> Self { + (&value).into() + } +} +impl From<Enum16> for i32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for i64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u32 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +impl From<Enum16> for u64 { + fn from(value: Enum16) -> Self { + u16::from(value) as Self + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Parent { + pub foo: Enum16, + pub bar: Enum16, + pub baz: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Parent> for Bytes { + type Error = EncodeError; + fn try_from(packet: &Parent) -> Result<Self, Self::Error> { + packet.encode_to_bytes() + } +} +impl TryFrom<&Parent> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: &Parent) -> Result<Self, Self::Error> { + packet.encode_to_vec() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ParentChild { + Child(Child), + None, +} +impl Parent { + pub fn specialize(&self) -> Result<ParentChild, DecodeError> { + Ok( + match (self.foo,) { + (Enum16::A,) => ParentChild::Child(self.try_into()?), + _ => ParentChild::None, + }, + ) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn foo(&self) -> Enum16 { + self.foo + } + pub fn bar(&self) -> Enum16 { + self.bar + } + pub fn baz(&self) -> Enum16 { + self.baz + } +} +impl Packet for Parent { + fn encoded_len(&self) -> usize { + 7 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(u16::from(self.foo())); + buf.put_u16_le(u16::from(self.bar())); + buf.put_u16_le(u16::from(self.baz())); + if self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(self.payload.len() as u8); + buf.put_slice(&self.payload); + Ok(()) + } + fn decode(mut buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let foo = Enum16::try_from(buf.get_u16_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "foo", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let bar = Enum16::try_from(buf.get_u16_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "bar", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 2, + got: buf.remaining(), + }); + } + let baz = Enum16::try_from(buf.get_u16_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Parent", + field: "baz", + value: unknown_val as u64, + type_: "Enum16", + })?; + if buf.remaining() < 1 { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: 1, + got: buf.remaining(), + }); + } + let payload_size = buf.get_u8() as usize; + if buf.remaining() < payload_size { + return Err(DecodeError::InvalidLengthError { + obj: "Parent", + wanted: payload_size, + got: buf.remaining(), + }); + } + let payload = buf[..payload_size].to_vec(); + buf.advance(payload_size); + let payload = Vec::from(payload); + Ok((Self { payload, foo, bar, baz }, buf)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Child { + pub quux: Enum16, + pub bar: Enum16, + pub baz: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Parent> for Child { + type Error = DecodeError; + fn try_from(parent: &Parent) -> Result<Child, Self::Error> { + Child::decode_partial(&parent) + } +} +impl TryFrom<&Child> for Parent { + type Error = EncodeError; + fn try_from(packet: &Child) -> Result<Parent, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Parent { + foo: Enum16::A, + bar: packet.bar, + baz: packet.baz, + payload, + }) + } +} +impl TryFrom<&Child> for Bytes { + type Error = EncodeError; + fn try_from(packet: &Child) -> Result<Self, Self::Error> { + packet.encode_to_bytes() + } +} +impl TryFrom<&Child> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: &Child) -> Result<Self, Self::Error> { + packet.encode_to_vec() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ChildChild { + GrandChild(GrandChild), + None, +} +impl Child { + pub fn specialize(&self) -> Result<ChildChild, DecodeError> { + Ok( + match (self.bar, self.quux) { + (Enum16::A, Enum16::A) => ChildChild::GrandChild(self.try_into()?), + _ => ChildChild::None, + }, + ) + } + fn decode_partial(parent: &Parent) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + if buf.remaining() < 2 { + return Err(DecodeError::InvalidLengthError { + obj: "Child", + wanted: 2, + got: buf.remaining(), + }); + } + let quux = Enum16::try_from(buf.get_u16_le()) + .map_err(|unknown_val| DecodeError::InvalidEnumValueError { + obj: "Child", + field: "quux", + value: unknown_val as u64, + type_: "Enum16", + })?; + let payload = buf.to_vec(); + buf.advance(payload.len()); + let payload = Vec::from(payload); + if buf.is_empty() { + Ok(Self { + payload, + quux, + bar: parent.bar, + baz: parent.baz, + }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(u16::from(self.quux())); + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn quux(&self) -> Enum16 { + self.quux + } + pub fn bar(&self) -> Enum16 { + self.bar + } + pub fn baz(&self) -> Enum16 { + self.baz + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for Child { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(u16::from(self.foo())); + buf.put_u16_le(u16::from(self.bar())); + buf.put_u16_le(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Parent::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GrandChild { + pub baz: Enum16, + pub payload: Vec<u8>, +} +impl TryFrom<&Child> for GrandChild { + type Error = DecodeError; + fn try_from(parent: &Child) -> Result<GrandChild, Self::Error> { + GrandChild::decode_partial(&parent) + } +} +impl TryFrom<&GrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Child, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(Child { + quux: Enum16::A, + bar: Enum16::A, + baz: packet.baz, + payload, + }) + } +} +impl TryFrom<&GrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Parent, Self::Error> { + (&Child::try_from(packet)?).try_into() + } +} +impl TryFrom<&GrandChild> for Bytes { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Self, Self::Error> { + packet.encode_to_bytes() + } +} +impl TryFrom<&GrandChild> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: &GrandChild) -> Result<Self, Self::Error> { + packet.encode_to_vec() + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum GrandChildChild { + GrandGrandChild(GrandGrandChild), + None, +} +impl GrandChild { + pub fn specialize(&self) -> Result<GrandChildChild, DecodeError> { + Ok( + match (self.baz,) { + (Enum16::A,) => GrandChildChild::GrandGrandChild(self.try_into()?), + _ => GrandChildChild::None, + }, + ) + } + fn decode_partial(parent: &Child) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + let payload = buf.to_vec(); + buf.advance(payload.len()); + let payload = Vec::from(payload); + if buf.is_empty() { + Ok(Self { payload, baz: parent.baz }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn baz(&self) -> Enum16 { + self.baz + } + pub fn quux(&self) -> Enum16 { + Enum16::A + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } + pub fn bar(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for GrandChild { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(u16::from(self.foo())); + buf.put_u16_le(u16::from(self.bar())); + buf.put_u16_le(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + buf.put_u16_le(u16::from(self.quux())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = Child::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GrandGrandChild { + pub payload: Vec<u8>, +} +impl TryFrom<&GrandChild> for GrandGrandChild { + type Error = DecodeError; + fn try_from(parent: &GrandChild) -> Result<GrandGrandChild, Self::Error> { + GrandGrandChild::decode_partial(&parent) + } +} +impl TryFrom<&GrandGrandChild> for GrandChild { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<GrandChild, Self::Error> { + let mut payload = Vec::new(); + packet.encode_partial(&mut payload)?; + Ok(GrandChild { + baz: Enum16::A, + payload, + }) + } +} +impl TryFrom<&GrandGrandChild> for Child { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Child, Self::Error> { + (&GrandChild::try_from(packet)?).try_into() + } +} +impl TryFrom<&GrandGrandChild> for Parent { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Parent, Self::Error> { + (&GrandChild::try_from(packet)?).try_into() + } +} +impl TryFrom<&GrandGrandChild> for Bytes { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Self, Self::Error> { + packet.encode_to_bytes() + } +} +impl TryFrom<&GrandGrandChild> for Vec<u8> { + type Error = EncodeError; + fn try_from(packet: &GrandGrandChild) -> Result<Self, Self::Error> { + packet.encode_to_vec() + } +} +impl GrandGrandChild { + fn decode_partial(parent: &GrandChild) -> Result<Self, DecodeError> { + let mut buf: &[u8] = &parent.payload; + let payload = buf.to_vec(); + buf.advance(payload.len()); + let payload = Vec::from(payload); + if buf.is_empty() { + Ok(Self { payload }) + } else { + Err(DecodeError::TrailingBytes) + } + } + pub fn encode_partial(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_slice(&self.payload); + Ok(()) + } + pub fn payload(&self) -> &[u8] { + &self.payload + } + pub fn quux(&self) -> Enum16 { + Enum16::A + } + pub fn foo(&self) -> Enum16 { + Enum16::A + } + pub fn bar(&self) -> Enum16 { + Enum16::A + } + pub fn baz(&self) -> Enum16 { + Enum16::A + } +} +impl Packet for GrandGrandChild { + fn encoded_len(&self) -> usize { + 9 + self.payload.len() + } + fn encode(&self, buf: &mut impl BufMut) -> Result<(), EncodeError> { + buf.put_u16_le(u16::from(self.foo())); + buf.put_u16_le(u16::from(self.bar())); + buf.put_u16_le(u16::from(self.baz())); + if 2 + self.payload.len() > 0xff { + return Err(EncodeError::SizeOverflow { + packet: "Parent", + field: "_payload_", + size: 2 + self.payload.len(), + maximum_size: 0xff, + }); + } + buf.put_u8(2 + self.payload.len() as u8); + buf.put_u16_le(u16::from(self.quux())); + self.encode_partial(buf)?; + Ok(()) + } + fn decode(buf: &[u8]) -> Result<(Self, &[u8]), DecodeError> { + let (parent, trailing_bytes) = GrandChild::decode(buf)?; + let packet = Self::decode_partial(&parent)?; + Ok((packet, trailing_bytes)) + } +} diff --git a/tests/python_generator_test.py b/tests/python_generator_test.py index a126c8d..1d3ab75 100644 --- a/tests/python_generator_test.py +++ b/tests/python_generator_test.py @@ -21,7 +21,6 @@ import dataclasses import enum import json import typing -import typing_extensions import unittest from importlib import resources @@ -33,6 +32,14 @@ import le_backend import be_backend +SKIPPED_TESTS = [ + "Packet_Array_Field_VariableElementSize_ConstantSize", + "Packet_Array_Field_VariableElementSize_VariableSize", + "Packet_Array_Field_VariableElementSize_VariableCount", + "Packet_Array_Field_VariableElementSize_UnknownSize", +] + + def match_object(self, left, right): """Recursively match a python class object against a reference json object.""" @@ -57,19 +64,20 @@ def create_object(typ, value): field_type = field_types[f] values[f] = create_object(field_type, v) return typ(**values) - elif typing_extensions.get_origin(typ) is list: - typ = typing_extensions.get_args(typ)[0] + elif typing.get_origin(typ) is list: + typ = typing.get_args(typ)[0] return [create_object(typ, v) for v in value] - elif typing_extensions.get_origin(typ) is typing.Union: + elif typing.get_origin(typ) is typing.Union: # typing.Optional[int] expands to typing.Union[int, None] - typ = typing_extensions.get_args(typ)[0] + typ = typing.get_args(typ)[0] return create_object(typ, value) if value is not None else None elif typ is bytes: return bytes(value) elif typ is bytearray: return bytearray(value) elif issubclass(typ, enum.Enum): - return typ(value) + from_int = getattr(typ, 'from_int') + return from_int(value) elif typ is int: return value else: @@ -90,6 +98,10 @@ class PacketParserTest(unittest.TestCase): # selected packet. packet = item['packet'] tests = item['tests'] + + if packet in SKIPPED_TESTS: + continue + with self.subTest(packet=packet): # Retrieve the class object from the generated # module, in order to invoke the proper parse @@ -109,6 +121,10 @@ class PacketParserTest(unittest.TestCase): # selected packet. packet = item['packet'] tests = item['tests'] + + if packet in SKIPPED_TESTS: + continue + with self.subTest(packet=packet): # Retrieve the class object from the generated # module, in order to invoke the proper constructor @@ -133,6 +149,10 @@ class PacketSerializerTest(unittest.TestCase): # selected packet. packet = item['packet'] tests = item['tests'] + + if packet in SKIPPED_TESTS: + continue + with self.subTest(packet=packet): # Retrieve the class object from the generated # module, in order to invoke the proper constructor @@ -153,6 +173,10 @@ class PacketSerializerTest(unittest.TestCase): # selected packet. packet = item['packet'] tests = item['tests'] + + if packet in SKIPPED_TESTS: + continue + with self.subTest(packet=packet): # Retrieve the class object from the generated # module, in order to invoke the proper parse diff --git a/tests/run_cxx_generator_tests.sh b/tests/run_cxx_generator_tests.sh index fa90323..862bd0a 100755 --- a/tests/run_cxx_generator_tests.sh +++ b/tests/run_cxx_generator_tests.sh @@ -18,10 +18,54 @@ pdlc "$OUT_DIR"/be_test_file.pdl > "$OUT_DIR"/be_test_file.json python3 scripts/generate_cxx_backend.py \ --input "$OUT_DIR"/le_test_file.json \ --output "$OUT_DIR"/le_backend.h \ + --exclude-declaration Packet_Custom_Field_ConstantSize \ + --exclude-declaration Packet_Custom_Field_VariableSize \ + --exclude-declaration Packet_Checksum_Field_FromStart \ + --exclude-declaration Packet_Checksum_Field_FromEnd \ + --exclude-declaration Packet_Array_Field_VariableElementSize_ConstantSize \ + --exclude-declaration Packet_Array_Field_VariableElementSize_VariableSize \ + --exclude-declaration Packet_Array_Field_VariableElementSize_VariableCount \ + --exclude-declaration Packet_Array_Field_VariableElementSize_UnknownSize \ + --exclude-declaration Struct_Custom_Field_ConstantSize \ + --exclude-declaration Struct_Custom_Field_VariableSize \ + --exclude-declaration Struct_Checksum_Field_FromStart \ + --exclude-declaration Struct_Checksum_Field_FromEnd \ + --exclude-declaration Struct_Custom_Field_ConstantSize_ \ + --exclude-declaration Struct_Custom_Field_VariableSize_ \ + --exclude-declaration Struct_Checksum_Field_FromStart_ \ + --exclude-declaration Struct_Checksum_Field_FromEnd_ \ + --exclude-declaration PartialParent5 \ + --exclude-declaration PartialChild5_A \ + --exclude-declaration PartialChild5_B \ + --exclude-declaration PartialParent12 \ + --exclude-declaration PartialChild12_A \ + --exclude-declaration PartialChild12_B \ --namespace le_backend python3 scripts/generate_cxx_backend.py \ --input "$OUT_DIR"/be_test_file.json \ --output "$OUT_DIR"/be_backend.h \ + --exclude-declaration Packet_Custom_Field_ConstantSize \ + --exclude-declaration Packet_Custom_Field_VariableSize \ + --exclude-declaration Packet_Checksum_Field_FromStart \ + --exclude-declaration Packet_Checksum_Field_FromEnd \ + --exclude-declaration Packet_Array_Field_VariableElementSize_ConstantSize \ + --exclude-declaration Packet_Array_Field_VariableElementSize_VariableSize \ + --exclude-declaration Packet_Array_Field_VariableElementSize_VariableCount \ + --exclude-declaration Packet_Array_Field_VariableElementSize_UnknownSize \ + --exclude-declaration Struct_Custom_Field_ConstantSize \ + --exclude-declaration Struct_Custom_Field_VariableSize \ + --exclude-declaration Struct_Checksum_Field_FromStart \ + --exclude-declaration Struct_Checksum_Field_FromEnd \ + --exclude-declaration Struct_Custom_Field_ConstantSize_ \ + --exclude-declaration Struct_Custom_Field_VariableSize_ \ + --exclude-declaration Struct_Checksum_Field_FromStart_ \ + --exclude-declaration Struct_Checksum_Field_FromEnd_ \ + --exclude-declaration PartialParent5 \ + --exclude-declaration PartialChild5_A \ + --exclude-declaration PartialChild5_B \ + --exclude-declaration PartialParent12 \ + --exclude-declaration PartialChild12_A \ + --exclude-declaration PartialChild12_B \ --namespace be_backend python3 scripts/generate_cxx_backend_tests.py \ diff --git a/tests/run_python_generator_tests.sh b/tests/run_python_generator_tests.sh index e11b8f5..3b90a92 100755 --- a/tests/run_python_generator_tests.sh +++ b/tests/run_python_generator_tests.sh @@ -18,10 +18,18 @@ pdlc "$OUT_DIR"/be_test_file.pdl > "$OUT_DIR"/be_test_file.json python3 scripts/generate_python_backend.py \ --input "$OUT_DIR"/le_test_file.json \ --output "$OUT_DIR"/le_backend.py \ + --exclude-declaration Packet_Array_Field_VariableElementSize_ConstantSize \ + --exclude-declaration Packet_Array_Field_VariableElementSize_VariableSize \ + --exclude-declaration Packet_Array_Field_VariableElementSize_VariableCount \ + --exclude-declaration Packet_Array_Field_VariableElementSize_UnknownSize \ --custom-type-location tests.custom_types python3 scripts/generate_python_backend.py \ --input "$OUT_DIR"/be_test_file.json \ --output "$OUT_DIR"/be_backend.py \ + --exclude-declaration Packet_Array_Field_VariableElementSize_ConstantSize \ + --exclude-declaration Packet_Array_Field_VariableElementSize_VariableSize \ + --exclude-declaration Packet_Array_Field_VariableElementSize_VariableCount \ + --exclude-declaration Packet_Array_Field_VariableElementSize_UnknownSize \ --custom-type-location tests.custom_types export PYTHONPATH="$OUT_DIR:.:${PYTHONPATH:-}" diff --git a/tests/run_rust_generator_tests.sh b/tests/run_rust_generator_tests.sh index 92e6f05..8d0eb67 100755 --- a/tests/run_rust_generator_tests.sh +++ b/tests/run_rust_generator_tests.sh @@ -37,8 +37,15 @@ cargo run --bin pdlc -- \ --exclude-declaration Packet_Array_Field_UnsizedElement_SizeModifier \ --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier_ \ --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier \ + --exclude-declaration Packet_Array_ElementSize_UnsizedCustomField \ + --exclude-declaration Packet_Array_ElementSize_SizedCustomField \ > "$OUT_DIR/canonical_test/src/le_backend.rs" cargo run --bin pdlc -- \ + tests/canonical/le_test_vectors.json \ + --output-format rust \ + --tests \ + >> "$OUT_DIR/canonical_test/src/le_backend.rs" +cargo run --bin pdlc -- \ "$OUT_DIR/be_test_file.pdl" \ --output-format rust \ --exclude-declaration UnsizedCustomField \ @@ -55,20 +62,18 @@ cargo run --bin pdlc -- \ --exclude-declaration Packet_Array_Field_UnsizedElement_SizeModifier \ --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier_ \ --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier \ + --exclude-declaration Packet_Array_ElementSize_UnsizedCustomField \ + --exclude-declaration Packet_Array_ElementSize_SizedCustomField \ > "$OUT_DIR/canonical_test/src/be_backend.rs" -cargo run --bin generate-canonical-tests -- \ - tests/canonical/le_test_vectors.json "crate::le_backend" \ - > "$OUT_DIR/canonical_test/src/le_backend_tests.rs" -cargo run --bin generate-canonical-tests -- \ - tests/canonical/be_test_vectors.json "crate::be_backend" \ - > "$OUT_DIR/canonical_test/src/be_backend_tests.rs" - +cargo run --bin pdlc -- \ + tests/canonical/be_test_vectors.json \ + --output-format rust \ + --tests \ + >> "$OUT_DIR/canonical_test/src/be_backend.rs" cat <<EOT > "$OUT_DIR/canonical_test/src/lib.rs" mod le_backend; -mod le_backend_tests; mod be_backend; -mod be_backend_tests; EOT cat <<EOT > "$OUT_DIR/canonical_test/Cargo.toml" diff --git a/tests/run_rust_legacy_generator_tests.sh b/tests/run_rust_legacy_generator_tests.sh new file mode 100755 index 0000000..53d49e7 --- /dev/null +++ b/tests/run_rust_legacy_generator_tests.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash + +set -euxo pipefail + +mkdir -p out/ +OUT_DIR="$(pwd)/out" + +# move to `pdl-compiler` directory +cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." &> /dev/null + +sed -e 's/little_endian_packets/big_endian_packets/' \ + -e '/Start: little_endian_only/,/End: little_endian_only/d' \ + < tests/canonical/le_test_file.pdl > "$OUT_DIR/be_test_file.pdl" + +mkdir -p "$OUT_DIR/canonical_test/src" + +cargo run --bin pdlc -- \ + tests/canonical/le_test_file.pdl \ + --output-format rust_legacy \ + --exclude-declaration UnsizedCustomField \ + --exclude-declaration Packet_Custom_Field_VariableSize \ + --exclude-declaration Struct_Custom_Field_VariableSize_ \ + --exclude-declaration Struct_Custom_Field_VariableSize \ + --exclude-declaration Checksum \ + --exclude-declaration Packet_Checksum_Field_FromStart \ + --exclude-declaration Packet_Checksum_Field_FromEnd \ + --exclude-declaration Struct_Checksum_Field_FromStart_ \ + --exclude-declaration Struct_Checksum_Field_FromStart \ + --exclude-declaration Struct_Checksum_Field_FromEnd_ \ + --exclude-declaration Struct_Checksum_Field_FromEnd \ + --exclude-declaration PartialParent5 \ + --exclude-declaration PartialParent12 \ + --exclude-declaration PartialChild5_A \ + --exclude-declaration PartialChild5_B \ + --exclude-declaration PartialChild12_A \ + --exclude-declaration PartialChild12_B \ + --exclude-declaration Packet_Array_Field_UnsizedElement_SizeModifier \ + --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier_ \ + --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier \ + --exclude-declaration Packet_Array_Field_VariableElementSize_ConstantSize \ + --exclude-declaration Packet_Array_Field_VariableElementSize_VariableSize \ + --exclude-declaration Packet_Array_Field_VariableElementSize_VariableCount \ + --exclude-declaration Packet_Array_Field_VariableElementSize_UnknownSize \ + > "$OUT_DIR/canonical_test/src/le_backend.rs" +cargo run --bin pdlc -- \ + tests/canonical/le_test_vectors.json \ + --output-format rust_legacy \ + --tests \ + >> "$OUT_DIR/canonical_test/src/le_backend.rs" +cargo run --bin pdlc -- \ + "$OUT_DIR/be_test_file.pdl" \ + --output-format rust_legacy \ + --exclude-declaration UnsizedCustomField \ + --exclude-declaration Packet_Custom_Field_VariableSize \ + --exclude-declaration Struct_Custom_Field_VariableSize_ \ + --exclude-declaration Struct_Custom_Field_VariableSize \ + --exclude-declaration Checksum \ + --exclude-declaration Packet_Checksum_Field_FromStart \ + --exclude-declaration Packet_Checksum_Field_FromEnd \ + --exclude-declaration Struct_Checksum_Field_FromStart_ \ + --exclude-declaration Struct_Checksum_Field_FromStart \ + --exclude-declaration Struct_Checksum_Field_FromEnd_ \ + --exclude-declaration Struct_Checksum_Field_FromEnd \ + --exclude-declaration Packet_Array_Field_UnsizedElement_SizeModifier \ + --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier_ \ + --exclude-declaration Struct_Array_Field_UnsizedElement_SizeModifier \ + --exclude-declaration Packet_Array_Field_VariableElementSize_ConstantSize \ + --exclude-declaration Packet_Array_Field_VariableElementSize_VariableSize \ + --exclude-declaration Packet_Array_Field_VariableElementSize_VariableCount \ + --exclude-declaration Packet_Array_Field_VariableElementSize_UnknownSize \ + > "$OUT_DIR/canonical_test/src/be_backend.rs" +cargo run --bin pdlc -- \ + tests/canonical/be_test_vectors.json \ + --output-format rust_legacy \ + --tests \ + >> "$OUT_DIR/canonical_test/src/be_backend.rs" + +cat <<EOT > "$OUT_DIR/canonical_test/src/lib.rs" +mod le_backend; +mod be_backend; +EOT + +cat <<EOT > "$OUT_DIR/canonical_test/Cargo.toml" +[package] +name = "canonical_test" +version = "0.0.0" +publish = false +edition = "2021" + +[features] +default = ["serde"] + +[dependencies] +bytes = {version = "1.4.0", features = ["serde"]} +thiserror = "1.0.47" +serde_json = "1.0.86" + +[dependencies.serde] +version = "1.0.145" +features = ["default", "derive", "serde_derive", "std", "rc"] +optional = true + +[dependencies.pdl-runtime] +path = "../../pdl-runtime" + +[workspace] +EOT + +cd "$OUT_DIR/canonical_test" +RUSTFLAGS=-Awarnings cargo test --tests |