aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cargo_vcs_info.json4
-rw-r--r--Android.bp258
-rw-r--r--CONTRIBUTING.md33
-rw-r--r--Cargo.toml2
-rw-r--r--Cargo.toml.orig2
-rw-r--r--METADATA23
-rw-r--r--README.md2
-rw-r--r--doc/cxx-generated-code-guide.rst47
-rw-r--r--doc/python-generated-code-guide.rst126
-rw-r--r--doc/reference.md692
-rw-r--r--doc/rust-generated-code-guide.rst98
-rw-r--r--examples/jpeg.pdl88
-rw-r--r--examples/pcap.pdl27
-rw-r--r--rustfmt.toml8
-rwxr-xr-xscripts/generate_cxx_backend.py39
-rwxr-xr-xscripts/generate_cxx_backend_tests.py4
-rwxr-xr-xscripts/generate_python_backend.py50
-rw-r--r--scripts/pdl/ast.py8
-rw-r--r--scripts/pdl/core.py6
-rw-r--r--src/analyzer.rs647
-rw-r--r--src/ast.rs121
-rw-r--r--src/backends.rs1
-rw-r--r--src/backends/intermediate.rs16
-rw-r--r--src/backends/json.rs4
-rw-r--r--src/backends/rust/mod.rs1723
-rw-r--r--src/backends/rust/parser.rs525
-rw-r--r--src/backends/rust/preamble.rs13
-rw-r--r--src/backends/rust/serializer.rs661
-rw-r--r--src/backends/rust/test.rs255
-rw-r--r--src/backends/rust/types.rs26
-rw-r--r--src/backends/rust_legacy/mod.rs (renamed from src/backends/rust.rs)127
-rw-r--r--src/backends/rust_legacy/parser.rs861
-rw-r--r--src/backends/rust_legacy/preamble.rs93
-rw-r--r--src/backends/rust_legacy/serializer.rs519
-rw-r--r--src/backends/rust_legacy/test.rs (renamed from src/bin/generate-canonical-tests.rs)42
-rw-r--r--src/backends/rust_legacy/types.rs186
-rw-r--r--src/backends/rust_no_allocation/mod.rs5
-rw-r--r--src/backends/rust_no_allocation/packet_parser.rs3
-rw-r--r--src/backends/rust_no_allocation/packet_serializer.rs3
-rw-r--r--src/backends/rust_no_allocation/utils.rs11
-rw-r--r--src/main.rs85
-rw-r--r--src/parser.rs189
-rw-r--r--tests/canonical/le_rust_test_file.pdl573
-rw-r--r--tests/canonical/le_test_file.pdl132
-rw-r--r--tests/canonical/le_test_vectors.json385
-rwxr-xr-xtests/compile_rust_generated_files.sh41
-rwxr-xr-xtests/compile_rust_legacy_generated_files.sh41
-rw-r--r--tests/generated/preamble.rs11
-rw-r--r--tests/generated/rust/custom_field_declaration_big_endian.rs102
-rw-r--r--tests/generated/rust/custom_field_declaration_little_endian.rs102
-rw-r--r--tests/generated/rust/enum_declaration_big_endian.rs (renamed from tests/generated/enum_declaration_big_endian.rs)25
-rw-r--r--tests/generated/rust/enum_declaration_little_endian.rs (renamed from tests/generated/enum_declaration_little_endian.rs)25
-rw-r--r--tests/generated/rust/packet_decl_24bit_enum_array_big_endian.rs115
-rw-r--r--tests/generated/rust/packet_decl_24bit_enum_array_little_endian.rs115
-rw-r--r--tests/generated/rust/packet_decl_24bit_enum_big_endian.rs107
-rw-r--r--tests/generated/rust/packet_decl_24bit_enum_little_endian.rs107
-rw-r--r--tests/generated/rust/packet_decl_24bit_scalar_array_big_endian.rs61
-rw-r--r--tests/generated/rust/packet_decl_24bit_scalar_array_little_endian.rs61
-rw-r--r--tests/generated/rust/packet_decl_24bit_scalar_big_endian.rs63
-rw-r--r--tests/generated/rust/packet_decl_24bit_scalar_little_endian.rs63
-rw-r--r--tests/generated/rust/packet_decl_64bit_enum_array_big_endian.rs100
-rw-r--r--tests/generated/rust/packet_decl_64bit_enum_array_little_endian.rs100
-rw-r--r--tests/generated/rust/packet_decl_64bit_enum_big_endian.rs92
-rw-r--r--tests/generated/rust/packet_decl_64bit_enum_little_endian.rs92
-rw-r--r--tests/generated/rust/packet_decl_64bit_scalar_array_big_endian.rs61
-rw-r--r--tests/generated/rust/packet_decl_64bit_scalar_array_little_endian.rs61
-rw-r--r--tests/generated/rust/packet_decl_64bit_scalar_big_endian.rs55
-rw-r--r--tests/generated/rust/packet_decl_64bit_scalar_little_endian.rs55
-rw-r--r--tests/generated/rust/packet_decl_8bit_enum_array_big_endian.rs130
-rw-r--r--tests/generated/rust/packet_decl_8bit_enum_array_little_endian.rs130
-rw-r--r--tests/generated/rust/packet_decl_8bit_enum_big_endian.rs122
-rw-r--r--tests/generated/rust/packet_decl_8bit_enum_little_endian.rs122
-rw-r--r--tests/generated/rust/packet_decl_8bit_scalar_array_big_endian.rs61
-rw-r--r--tests/generated/rust/packet_decl_8bit_scalar_array_little_endian.rs61
-rw-r--r--tests/generated/rust/packet_decl_8bit_scalar_big_endian.rs55
-rw-r--r--tests/generated/rust/packet_decl_8bit_scalar_little_endian.rs55
-rw-r--r--tests/generated/rust/packet_decl_array_dynamic_count_big_endian.rs91
-rw-r--r--tests/generated/rust/packet_decl_array_dynamic_count_little_endian.rs91
-rw-r--r--tests/generated/rust/packet_decl_array_dynamic_element_size_big_endian.rs146
-rw-r--r--tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_count_big_endian.rs143
-rw-r--r--tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_count_little_endian.rs143
-rw-r--r--tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_size_big_endian.rs150
-rw-r--r--tests/generated/rust/packet_decl_array_dynamic_element_size_dynamic_size_little_endian.rs150
-rw-r--r--tests/generated/rust/packet_decl_array_dynamic_element_size_little_endian.rs146
-rw-r--r--tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_1_big_endian.rs148
-rw-r--r--tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_1_little_endian.rs148
-rw-r--r--tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_big_endian.rs148
-rw-r--r--tests/generated/rust/packet_decl_array_dynamic_element_size_static_count_little_endian.rs148
-rw-r--r--tests/generated/rust/packet_decl_array_dynamic_size_big_endian.rs99
-rw-r--r--tests/generated/rust/packet_decl_array_dynamic_size_little_endian.rs99
-rw-r--r--tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_count_big_endian.rs120
-rw-r--r--tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_count_little_endian.rs120
-rw-r--r--tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_size_big_endian.rs131
-rw-r--r--tests/generated/rust/packet_decl_array_unknown_element_width_dynamic_size_little_endian.rs131
-rw-r--r--tests/generated/rust/packet_decl_array_with_padding_big_endian.rs123
-rw-r--r--tests/generated/rust/packet_decl_array_with_padding_little_endian.rs123
-rw-r--r--tests/generated/rust/packet_decl_child_packets_big_endian.rs372
-rw-r--r--tests/generated/rust/packet_decl_child_packets_little_endian.rs372
-rw-r--r--tests/generated/rust/packet_decl_complex_scalars_big_endian.rs141
-rw-r--r--tests/generated/rust/packet_decl_complex_scalars_little_endian.rs141
-rw-r--r--tests/generated/rust/packet_decl_custom_field_big_endian.rs131
-rw-r--r--tests/generated/rust/packet_decl_custom_field_little_endian.rs131
-rw-r--r--tests/generated/rust/packet_decl_empty_big_endian.rs40
-rw-r--r--tests/generated/rust/packet_decl_empty_little_endian.rs40
-rw-r--r--tests/generated/rust/packet_decl_fixed_enum_field_big_endian.rs138
-rw-r--r--tests/generated/rust/packet_decl_fixed_enum_field_little_endian.rs138
-rw-r--r--tests/generated/rust/packet_decl_fixed_scalar_field_big_endian.rs72
-rw-r--r--tests/generated/rust/packet_decl_fixed_scalar_field_little_endian.rs72
-rw-r--r--tests/generated/rust/packet_decl_grand_children_big_endian.rs594
-rw-r--r--tests/generated/rust/packet_decl_grand_children_little_endian.rs594
-rw-r--r--tests/generated/rust/packet_decl_mask_scalar_value_big_endian.rs91
-rw-r--r--tests/generated/rust/packet_decl_mask_scalar_value_little_endian.rs91
-rw-r--r--tests/generated/rust/packet_decl_mixed_scalars_enums_big_endian.rs223
-rw-r--r--tests/generated/rust/packet_decl_mixed_scalars_enums_little_endian.rs223
-rw-r--r--tests/generated/rust/packet_decl_parent_with_alias_child_big_endian.rs461
-rw-r--r--tests/generated/rust/packet_decl_parent_with_alias_child_little_endian.rs461
-rw-r--r--tests/generated/rust/packet_decl_parent_with_no_payload_big_endian.rs191
-rw-r--r--tests/generated/rust/packet_decl_parent_with_no_payload_little_endian.rs191
-rw-r--r--tests/generated/rust/packet_decl_payload_field_unknown_size_big_endian.rs70
-rw-r--r--tests/generated/rust/packet_decl_payload_field_unknown_size_little_endian.rs70
-rw-r--r--tests/generated/rust/packet_decl_payload_field_unknown_size_terminal_big_endian.rs77
-rw-r--r--tests/generated/rust/packet_decl_payload_field_unknown_size_terminal_little_endian.rs77
-rw-r--r--tests/generated/rust/packet_decl_payload_field_variable_size_big_endian.rs99
-rw-r--r--tests/generated/rust/packet_decl_payload_field_variable_size_little_endian.rs99
-rw-r--r--tests/generated/rust/packet_decl_reserved_field_big_endian.rs49
-rw-r--r--tests/generated/rust/packet_decl_reserved_field_little_endian.rs49
-rw-r--r--tests/generated/rust/packet_decl_simple_scalars_big_endian.rs89
-rw-r--r--tests/generated/rust/packet_decl_simple_scalars_little_endian.rs89
-rw-r--r--tests/generated/rust/payload_with_size_modifier_big_endian.rs81
-rw-r--r--tests/generated/rust/payload_with_size_modifier_little_endian.rs81
-rw-r--r--tests/generated/rust/reserved_identifier_big_endian.rs55
-rw-r--r--tests/generated/rust/reserved_identifier_little_endian.rs55
-rw-r--r--tests/generated/rust/struct_decl_child_structs_big_endian.rs373
-rw-r--r--tests/generated/rust/struct_decl_child_structs_little_endian.rs373
-rw-r--r--tests/generated/rust/struct_decl_complex_scalars_big_endian.rs141
-rw-r--r--tests/generated/rust/struct_decl_complex_scalars_little_endian.rs141
-rw-r--r--tests/generated/rust/struct_decl_grand_children_big_endian.rs598
-rw-r--r--tests/generated/rust/struct_decl_grand_children_little_endian.rs598
-rw-r--r--tests/generated/rust_legacy/custom_field_declaration_big_endian.rs (renamed from tests/generated/custom_field_declaration_big_endian.rs)13
-rw-r--r--tests/generated/rust_legacy/custom_field_declaration_little_endian.rs (renamed from tests/generated/custom_field_declaration_little_endian.rs)13
-rw-r--r--tests/generated/rust_legacy/enum_declaration_big_endian.rs521
-rw-r--r--tests/generated/rust_legacy/enum_declaration_little_endian.rs521
-rw-r--r--tests/generated/rust_legacy/packet_decl_24bit_enum_array_big_endian.rs (renamed from tests/generated/packet_decl_24bit_enum_array_big_endian.rs)71
-rw-r--r--tests/generated/rust_legacy/packet_decl_24bit_enum_array_little_endian.rs (renamed from tests/generated/packet_decl_24bit_enum_array_little_endian.rs)71
-rw-r--r--tests/generated/rust_legacy/packet_decl_24bit_enum_big_endian.rs (renamed from tests/generated/packet_decl_24bit_enum_big_endian.rs)67
-rw-r--r--tests/generated/rust_legacy/packet_decl_24bit_enum_little_endian.rs (renamed from tests/generated/packet_decl_24bit_enum_little_endian.rs)67
-rw-r--r--tests/generated/rust_legacy/packet_decl_24bit_scalar_array_big_endian.rs (renamed from tests/generated/packet_decl_24bit_scalar_array_big_endian.rs)63
-rw-r--r--tests/generated/rust_legacy/packet_decl_24bit_scalar_array_little_endian.rs (renamed from tests/generated/packet_decl_24bit_scalar_array_little_endian.rs)63
-rw-r--r--tests/generated/rust_legacy/packet_decl_24bit_scalar_big_endian.rs (renamed from tests/generated/packet_decl_24bit_scalar_big_endian.rs)64
-rw-r--r--tests/generated/rust_legacy/packet_decl_24bit_scalar_little_endian.rs (renamed from tests/generated/packet_decl_24bit_scalar_little_endian.rs)64
-rw-r--r--tests/generated/rust_legacy/packet_decl_64bit_enum_array_big_endian.rs (renamed from tests/generated/packet_decl_64bit_enum_array_big_endian.rs)71
-rw-r--r--tests/generated/rust_legacy/packet_decl_64bit_enum_array_little_endian.rs (renamed from tests/generated/packet_decl_64bit_enum_array_little_endian.rs)71
-rw-r--r--tests/generated/rust_legacy/packet_decl_64bit_enum_big_endian.rs (renamed from tests/generated/packet_decl_64bit_enum_big_endian.rs)67
-rw-r--r--tests/generated/rust_legacy/packet_decl_64bit_enum_little_endian.rs (renamed from tests/generated/packet_decl_64bit_enum_little_endian.rs)67
-rw-r--r--tests/generated/rust_legacy/packet_decl_64bit_scalar_array_big_endian.rs (renamed from tests/generated/packet_decl_64bit_scalar_array_big_endian.rs)63
-rw-r--r--tests/generated/rust_legacy/packet_decl_64bit_scalar_array_little_endian.rs (renamed from tests/generated/packet_decl_64bit_scalar_array_little_endian.rs)63
-rw-r--r--tests/generated/rust_legacy/packet_decl_64bit_scalar_big_endian.rs (renamed from tests/generated/packet_decl_64bit_scalar_big_endian.rs)57
-rw-r--r--tests/generated/rust_legacy/packet_decl_64bit_scalar_little_endian.rs (renamed from tests/generated/packet_decl_64bit_scalar_little_endian.rs)57
-rw-r--r--tests/generated/rust_legacy/packet_decl_8bit_enum_array_big_endian.rs (renamed from tests/generated/packet_decl_8bit_enum_array_big_endian.rs)71
-rw-r--r--tests/generated/rust_legacy/packet_decl_8bit_enum_array_little_endian.rs (renamed from tests/generated/packet_decl_8bit_enum_array_little_endian.rs)71
-rw-r--r--tests/generated/rust_legacy/packet_decl_8bit_enum_big_endian.rs (renamed from tests/generated/packet_decl_8bit_enum_big_endian.rs)67
-rw-r--r--tests/generated/rust_legacy/packet_decl_8bit_enum_little_endian.rs (renamed from tests/generated/packet_decl_8bit_enum_little_endian.rs)67
-rw-r--r--tests/generated/rust_legacy/packet_decl_8bit_scalar_array_big_endian.rs (renamed from tests/generated/packet_decl_8bit_scalar_array_big_endian.rs)63
-rw-r--r--tests/generated/rust_legacy/packet_decl_8bit_scalar_array_little_endian.rs (renamed from tests/generated/packet_decl_8bit_scalar_array_little_endian.rs)63
-rw-r--r--tests/generated/rust_legacy/packet_decl_8bit_scalar_big_endian.rs (renamed from tests/generated/packet_decl_8bit_scalar_big_endian.rs)57
-rw-r--r--tests/generated/rust_legacy/packet_decl_8bit_scalar_little_endian.rs (renamed from tests/generated/packet_decl_8bit_scalar_little_endian.rs)57
-rw-r--r--tests/generated/rust_legacy/packet_decl_array_dynamic_count_big_endian.rs (renamed from tests/generated/packet_decl_array_dynamic_count_big_endian.rs)81
-rw-r--r--tests/generated/rust_legacy/packet_decl_array_dynamic_count_little_endian.rs (renamed from tests/generated/packet_decl_array_dynamic_count_little_endian.rs)81
-rw-r--r--tests/generated/rust_legacy/packet_decl_array_dynamic_size_big_endian.rs (renamed from tests/generated/packet_decl_array_dynamic_size_big_endian.rs)84
-rw-r--r--tests/generated/rust_legacy/packet_decl_array_dynamic_size_little_endian.rs (renamed from tests/generated/packet_decl_array_dynamic_size_little_endian.rs)84
-rw-r--r--tests/generated/rust_legacy/packet_decl_array_unknown_element_width_dynamic_count_big_endian.rs (renamed from tests/generated/packet_decl_array_unknown_element_width_dynamic_count_big_endian.rs)100
-rw-r--r--tests/generated/rust_legacy/packet_decl_array_unknown_element_width_dynamic_count_little_endian.rs (renamed from tests/generated/packet_decl_array_unknown_element_width_dynamic_count_little_endian.rs)100
-rw-r--r--tests/generated/rust_legacy/packet_decl_array_unknown_element_width_dynamic_size_big_endian.rs (renamed from tests/generated/packet_decl_array_unknown_element_width_dynamic_size_big_endian.rs)102
-rw-r--r--tests/generated/rust_legacy/packet_decl_array_unknown_element_width_dynamic_size_little_endian.rs (renamed from tests/generated/packet_decl_array_unknown_element_width_dynamic_size_little_endian.rs)102
-rw-r--r--tests/generated/rust_legacy/packet_decl_array_with_padding_big_endian.rs (renamed from tests/generated/packet_decl_array_with_padding_big_endian.rs)104
-rw-r--r--tests/generated/rust_legacy/packet_decl_array_with_padding_little_endian.rs (renamed from tests/generated/packet_decl_array_with_padding_little_endian.rs)104
-rw-r--r--tests/generated/rust_legacy/packet_decl_child_packets_big_endian.rs (renamed from tests/generated/packet_decl_child_packets_big_endian.rs)197
-rw-r--r--tests/generated/rust_legacy/packet_decl_child_packets_little_endian.rs (renamed from tests/generated/packet_decl_child_packets_little_endian.rs)197
-rw-r--r--tests/generated/rust_legacy/packet_decl_complex_scalars_big_endian.rs (renamed from tests/generated/packet_decl_complex_scalars_big_endian.rs)100
-rw-r--r--tests/generated/rust_legacy/packet_decl_complex_scalars_little_endian.rs (renamed from tests/generated/packet_decl_complex_scalars_little_endian.rs)100
-rw-r--r--tests/generated/rust_legacy/packet_decl_custom_field_big_endian.rs (renamed from tests/generated/packet_decl_custom_field_big_endian.rs)55
-rw-r--r--tests/generated/rust_legacy/packet_decl_custom_field_little_endian.rs (renamed from tests/generated/packet_decl_custom_field_little_endian.rs)55
-rw-r--r--tests/generated/rust_legacy/packet_decl_empty_big_endian.rs (renamed from tests/generated/packet_decl_empty_big_endian.rs)54
-rw-r--r--tests/generated/rust_legacy/packet_decl_empty_little_endian.rs (renamed from tests/generated/packet_decl_empty_little_endian.rs)54
-rw-r--r--tests/generated/rust_legacy/packet_decl_fixed_enum_field_big_endian.rs (renamed from tests/generated/packet_decl_fixed_enum_field_big_endian.rs)71
-rw-r--r--tests/generated/rust_legacy/packet_decl_fixed_enum_field_little_endian.rs (renamed from tests/generated/packet_decl_fixed_enum_field_little_endian.rs)71
-rw-r--r--tests/generated/rust_legacy/packet_decl_fixed_scalar_field_big_endian.rs (renamed from tests/generated/packet_decl_fixed_scalar_field_big_endian.rs)69
-rw-r--r--tests/generated/rust_legacy/packet_decl_fixed_scalar_field_little_endian.rs (renamed from tests/generated/packet_decl_fixed_scalar_field_little_endian.rs)69
-rw-r--r--tests/generated/rust_legacy/packet_decl_grand_children_big_endian.rs (renamed from tests/generated/packet_decl_grand_children_big_endian.rs)280
-rw-r--r--tests/generated/rust_legacy/packet_decl_grand_children_little_endian.rs (renamed from tests/generated/packet_decl_grand_children_little_endian.rs)280
-rw-r--r--tests/generated/rust_legacy/packet_decl_mask_scalar_value_big_endian.rs (renamed from tests/generated/packet_decl_mask_scalar_value_big_endian.rs)78
-rw-r--r--tests/generated/rust_legacy/packet_decl_mask_scalar_value_little_endian.rs (renamed from tests/generated/packet_decl_mask_scalar_value_little_endian.rs)78
-rw-r--r--tests/generated/rust_legacy/packet_decl_mixed_scalars_enums_big_endian.rs (renamed from tests/generated/packet_decl_mixed_scalars_enums_big_endian.rs)91
-rw-r--r--tests/generated/rust_legacy/packet_decl_mixed_scalars_enums_little_endian.rs (renamed from tests/generated/packet_decl_mixed_scalars_enums_little_endian.rs)91
-rw-r--r--tests/generated/rust_legacy/packet_decl_parent_with_alias_child_big_endian.rs (renamed from tests/generated/packet_decl_parent_with_alias_child_big_endian.rs)273
-rw-r--r--tests/generated/rust_legacy/packet_decl_parent_with_alias_child_little_endian.rs (renamed from tests/generated/packet_decl_parent_with_alias_child_little_endian.rs)273
-rw-r--r--tests/generated/rust_legacy/packet_decl_parent_with_no_payload_big_endian.rs (renamed from tests/generated/packet_decl_parent_with_no_payload_big_endian.rs)116
-rw-r--r--tests/generated/rust_legacy/packet_decl_parent_with_no_payload_little_endian.rs (renamed from tests/generated/packet_decl_parent_with_no_payload_little_endian.rs)116
-rw-r--r--tests/generated/rust_legacy/packet_decl_payload_field_unknown_size_big_endian.rs (renamed from tests/generated/packet_decl_payload_field_unknown_size_big_endian.rs)64
-rw-r--r--tests/generated/rust_legacy/packet_decl_payload_field_unknown_size_little_endian.rs (renamed from tests/generated/packet_decl_payload_field_unknown_size_little_endian.rs)64
-rw-r--r--tests/generated/rust_legacy/packet_decl_payload_field_unknown_size_terminal_big_endian.rs (renamed from tests/generated/packet_decl_payload_field_unknown_size_terminal_big_endian.rs)68
-rw-r--r--tests/generated/rust_legacy/packet_decl_payload_field_unknown_size_terminal_little_endian.rs (renamed from tests/generated/packet_decl_payload_field_unknown_size_terminal_little_endian.rs)68
-rw-r--r--tests/generated/rust_legacy/packet_decl_payload_field_variable_size_big_endian.rs (renamed from tests/generated/packet_decl_payload_field_variable_size_big_endian.rs)79
-rw-r--r--tests/generated/rust_legacy/packet_decl_payload_field_variable_size_little_endian.rs (renamed from tests/generated/packet_decl_payload_field_variable_size_little_endian.rs)79
-rw-r--r--tests/generated/rust_legacy/packet_decl_reserved_field_big_endian.rs (renamed from tests/generated/packet_decl_reserved_field_big_endian.rs)57
-rw-r--r--tests/generated/rust_legacy/packet_decl_reserved_field_little_endian.rs (renamed from tests/generated/packet_decl_reserved_field_little_endian.rs)57
-rw-r--r--tests/generated/rust_legacy/packet_decl_simple_scalars_big_endian.rs (renamed from tests/generated/packet_decl_simple_scalars_big_endian.rs)72
-rw-r--r--tests/generated/rust_legacy/packet_decl_simple_scalars_little_endian.rs (renamed from tests/generated/packet_decl_simple_scalars_little_endian.rs)72
-rw-r--r--tests/generated/rust_legacy/payload_with_size_modifier_big_endian.rs (renamed from tests/generated/payload_with_size_modifier_big_endian.rs)75
-rw-r--r--tests/generated/rust_legacy/payload_with_size_modifier_little_endian.rs (renamed from tests/generated/payload_with_size_modifier_little_endian.rs)75
-rw-r--r--tests/generated/rust_legacy/preamble.rs25
-rw-r--r--tests/generated/rust_legacy/reserved_identifier_big_endian.rs (renamed from tests/generated/reserved_identifier_big_endian.rs)57
-rw-r--r--tests/generated/rust_legacy/reserved_identifier_little_endian.rs (renamed from tests/generated/reserved_identifier_little_endian.rs)57
-rw-r--r--tests/generated/rust_legacy/struct_decl_complex_scalars_big_endian.rs (renamed from tests/generated/struct_decl_complex_scalars_big_endian.rs)65
-rw-r--r--tests/generated/rust_legacy/struct_decl_complex_scalars_little_endian.rs (renamed from tests/generated/struct_decl_complex_scalars_little_endian.rs)65
-rw-r--r--tests/generated/struct_decl_child_structs_big_endian.rs369
-rw-r--r--tests/generated/struct_decl_child_structs_little_endian.rs369
-rw-r--r--tests/generated/struct_decl_grand_children_big_endian.rs560
-rw-r--r--tests/generated/struct_decl_grand_children_little_endian.rs560
-rw-r--r--tests/python_generator_test.py36
-rwxr-xr-xtests/run_cxx_generator_tests.sh44
-rwxr-xr-xtests/run_python_generator_tests.sh8
-rwxr-xr-xtests/run_rust_generator_tests.sh23
-rwxr-xr-xtests/run_rust_legacy_generator_tests.sh110
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
diff --git a/Android.bp b/Android.bp
index 335643b..1708971 100644
--- a/Android.bp
+++ b/Android.bp
@@ -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.
diff --git a/Cargo.toml b/Cargo.toml
index b0aa493..c89b1ff 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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/"
diff --git a/METADATA b/METADATA
index 0680736..8ffef1d 100644
--- a/METADATA
+++ b/METADATA
@@ -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"
}
}
diff --git a/README.md b/README.md
index 1396b3d..a8e96fc 100644
--- a/README.md
+++ b/README.md
@@ -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:\
-> &nbsp;&nbsp; endianess [declaration](#declarations)*
->
-> endianess:\
-> &nbsp;&nbsp; `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}\
-> &nbsp;&nbsp; [enum_declaration](#enum) |\
-> &nbsp;&nbsp; [packet_declaration](#packet) |\
-> &nbsp;&nbsp; [struct_declaration](#struct) |\
-> &nbsp;&nbsp; [group_declaration](#group) |\
-> &nbsp;&nbsp; [checksum_declaration](#checksum) |\
-> &nbsp;&nbsp; [custom_field_declaration](#custom-field) |\
-> &nbsp;&nbsp; [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:\
-> &nbsp;&nbsp; `enum` [IDENTIFIER](#identifier) `:` [INTEGER](#integer) `{`\
-> &nbsp;&nbsp;&nbsp;&nbsp; enum_tag_list\
-> &nbsp;&nbsp; `}`
->
-> enum_tag_list:\
-> &nbsp;&nbsp; enum_tag (`,` enum_tag)* `,`?
->
-> enum_tag:\
-> &nbsp;&nbsp; enum_range | enum_value | enum_other
->
-> enum_range:\
-> &nbsp;&nbsp; [IDENTIFIER](#identifier) `=` [INTEGER](#integer) `..` [INTEGER](#integer)) (`{`\
-> &nbsp;&nbsp;&nbsp;&nbsp; enum_value_list\
-> &nbsp;&nbsp; `}`)?
->
-> enum_value_list:\
-> &nbsp;&nbsp; enum_value (`,` enum_value)* `,`?
->
-> enum_value:\
-> &nbsp;&nbsp; [IDENTIFIER](#identifier) `=` [INTEGER](#integer)
->
-> enum_other:\
-> &nbsp;&nbsp; [IDENTIFIER](#identifier) `=` `..`
-
-An *enumeration* or for short *enum*, is a declaration of a set of named [integer](#integer) constants
-or named [integer](#integer) ranges. [integer](#integer) ranges are inclusive in both ends.
-[integer](#integer) value within a range *must* be unique. [integer](#integer) ranges
-*must not* overlap.
-
-*enumeration* are closed by default, all values that are not explicitely described in the declaration are treated as invalid and _may_ cause a parsing error.
-
-An *enumaration* _may_ be declared open by specifiying the default case; all unrecognized values
-_shall_ falltrough to the default.
-
-The [integer](#integer) following the name specifies the bit size of the values.
-
-```
-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:\
-> &nbsp;&nbsp; `packet` [IDENTIFIER](#identifier)\
-> &nbsp;&nbsp;&nbsp;&nbsp; (`:` [IDENTIFIER](#identifier)\
-> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (`(` [constraint_list](#constraints) `)`)?\
-> &nbsp;&nbsp;&nbsp;&nbsp; )?\
-> &nbsp;&nbsp; `{`\
-> &nbsp;&nbsp;&nbsp;&nbsp; [field_list](#fields)?\
-> &nbsp;&nbsp; `}`
-
-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:\
-> &nbsp;&nbsp; `struct` [IDENTIFIER](#identifier)\
-> &nbsp;&nbsp;&nbsp;&nbsp; (`:` [IDENTIFIER](#identifier)\
-> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (`(` [constraint_list](#constraints) `)`)?\
-> &nbsp;&nbsp;&nbsp;&nbsp; )?\
-> &nbsp;&nbsp; `{`\
-> &nbsp;&nbsp;&nbsp;&nbsp; [field_list](#fields)?\
-> &nbsp;&nbsp; `}`
-
-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:\
-> &nbsp;&nbsp; `group` [IDENTIFIER](#identifier) `{`\
-> &nbsp;&nbsp;&nbsp;&nbsp; [field_list](#fields)\
-> &nbsp;&nbsp; `}`
-
-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:\
-> &nbsp;&nbsp; `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:\
-> &nbsp;&nbsp; `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:\
-> &nbsp;&nbsp; `test` [IDENTIFIER](#identifier) `{`\
-> &nbsp;&nbsp;&nbsp;&nbsp; test_case_list\
-> &nbsp;&nbsp; `}`
->
-> test_case_list:\
-> &nbsp;&nbsp; test_case (`,` test_case)* `,`?
->
-> test_case:\
-> &nbsp;&nbsp; [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:\
-> &nbsp;&nbsp; [IDENTIFIER](#identifier) `=` [IDENTIFIER](#identifier) | [INTEGER](#integer)
->
-> constraint_list:\
-> &nbsp;&nbsp; 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:\
-> &nbsp;&nbsp; field (`,` field)* `,`?
->
-> field:\
-> &nbsp;&nbsp; [checksum_field](#fields-checksum) |\
-> &nbsp;&nbsp; [padding_field](#fields-padding) |\
-> &nbsp;&nbsp; [size_field](#fields-size) |\
-> &nbsp;&nbsp; [count_field](#fields-count) |\
-> &nbsp;&nbsp; [payload_field](#fields-payload) |\
-> &nbsp;&nbsp; [body_field](#fields-body) |\
-> &nbsp;&nbsp; [fixed_field](#fields-fixed) |\
-> &nbsp;&nbsp; [reserved_field](#fields-reserved) |\
-> &nbsp;&nbsp; [array_field](#fields-array) |\
-> &nbsp;&nbsp; [scalar_field](#fields-scalar) |\
-> &nbsp;&nbsp; [typedef_field](#fields-typedef) |\
-> &nbsp;&nbsp; [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:\
-> &nbsp;&nbsp; [IDENTIFIER](#identifier) `:` [INTEGER](#integer)
-
-A *scalar* field defines a numeric value with a bit size.
-
-```
-struct Coffee {
- temperature: 8
-}
-```
-
-### Typedef {#fields-typedef}
-
-> typedef_field:\
-> &nbsp;&nbsp; [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:\
-> &nbsp;&nbsp; [IDENTIFIER](#identifier) `:` [INTEGER](#integer) | [IDENTIFIER](#identifier) `[`\
-> &nbsp;&nbsp;&nbsp;&nbsp; [SIZE_MODIFIER](#size-modifier) | [INTEGER](#integer)\
-> &nbsp;&nbsp; `]`
-
-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:\
-> &nbsp;&nbsp; [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:\
-> &nbsp;&nbsp; `_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:\
-> &nbsp;&nbsp; `_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:\
-> &nbsp;&nbsp; `_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:\
-> &nbsp;&nbsp; `_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:\
-> &nbsp;&nbsp; `_fixed_` `=` \
-> &nbsp;&nbsp;&nbsp;&nbsp; ( [INTEGER](#integer) `:` [INTEGER](#integer) ) |\
-> &nbsp;&nbsp;&nbsp;&nbsp; ( [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:\
-> &nbsp;&nbsp; `_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:\
-> &nbsp;&nbsp; `_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:\
-> &nbsp;&nbsp; `_reserved_` `:` [INTEGER](#integer)
-
-A *\_reserved\_* field adds reserved bits.
-
-```
-packet DeloreanCoffee {
- _reserved_: 2014
-}
-```
-
-## Tokens
-
-### Integer
-
-> INTEGER:\
-> &nbsp;&nbsp; HEXVALUE | INTVALUE
->
-> HEXVALUE:\
-> &nbsp;&nbsp; `0x` | `0X` HEXDIGIT<sup>+</sup>
->
-> INTVALUE:\
-> &nbsp;&nbsp; DIGIT<sup>+</sup>
->
-> HEXDIGIT:\
-> &nbsp;&nbsp; DIGIT | [`a`-`f`] | [`A`-`F`]
->
-> DIGIT:\
-> &nbsp;&nbsp; [`0`-`9`]
-
-A integer is a number in base 10 (decimal) or in base 16 (hexadecimal) with
-the prefix `0x`
-
-### String
-
-> STRING:\
-> &nbsp;&nbsp; `"` (!`"` __ANY__)* `"`
-
-A string is sequence of character. It can be multi-line.
-
-### Identifier
-
-> IDENTIFIER: \
-> &nbsp;&nbsp; ALPHA (ALPHANUM | `_`)*
->
-> ALPHA:\
-> &nbsp;&nbsp; [`a`-`z`] | [`A`-`Z`]
->
-> ALPHANUM:\
-> &nbsp;&nbsp; ALPHA | DIGIT
-
-An identifier is a sequence of alphanumeric or `_` characters
-starting with a letter.
-
-### Size Modifier
-
-> SIZE_MODIFIER:\
-> &nbsp;&nbsp; `+` 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:\
-> &nbsp;&nbsp; BLOCK_COMMENT | LINE_COMMENT
->
-> BLOCK_COMMENT:\
-> &nbsp;&nbsp; `/*` (!`*/` ANY) `*/`
->
-> LINE_COMMENT:\
-> &nbsp;&nbsp; `//` (!\n ANY) `//`
-
-### Whitespace
-
-> WHITESPACE:\
-> &nbsp;&nbsp; ` ` | `\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")
}
diff --git a/src/ast.rs b/src/ast.rs
index 20d8bb8..e545c5e 100644
--- a/src/ast.rs
+++ b/src/ast.rs
@@ -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,
+ &quote! { #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, &quote!(#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, &quote!(#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, &quote!(#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, &quote! { #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, &quote!(#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, &quote!(#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, &quote!(#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, &quote!(#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, &quote!(#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, &quote!(#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,
+ &quote! { #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, &quote!(*#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, &quote!(*#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,
&quote!(#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, &quote!(value), self.shift, self.span);
- self.code.push(quote! {
+ let put =
+ types::put_uint(self.endianness, &quote!(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,
&quote!(#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,
- &quote! { #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, &quote! { #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, &quote!(#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, &quote!(#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, &quote!(#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, &quote! { #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, &quote!(#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, &quote!(#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, &quote!(#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, &quote!(#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, &quote!(*#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,
+ &quote!(#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, &quote!(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,
+ &quote!(#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,
+ &quote! { #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